教父的告白
一切都是纸老虎
posts - 82,  comments - 7,  trackbacks - 0
Code Profiler :

在AX3+SP3中有一个工具Code Profiler,近来发现是非常好用的工具,可以检查代码运行的轨迹,以及代码运行的时间,对于跟踪代码是非常有效的。


C++代码度量工具-cccc
软件度量多个指标依赖于代码行统计,如每千行代码发现bug等,所以代码行是一个基础数据。CCCC度量数据可结合测试风险完善测试计划。


CodeStatistics
一个小的命令行工具。我主要用它来做两件事情,一者是代码统计功能;另一者是删除空白行功能。在某此时候,我觉得对于整理代码和了解代码情况还是有一定的帮助作用的。明天我会将代码的行结束符格式加上的,当然,还有分析代码元素,如有多少个函数,多少个类,也在我确定要添加的功能之内。当然,能整理代码就更棒了。


静态代码分析工具Cppcheck
Cppcheck是一款开源c++静态代码分析工具,在检测源码时可根据规则就能挖掘出疑似缺陷, 帮开源项目发现的bug:

http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Found_bugs

功能比较强大,使用很简单



 

posted @ 2010-09-13 16:45 暗夜教父 阅读(540) | 评论 (0)编辑 收藏
     摘要: 1.什么是canvas:引用Firefox开发者中心的一段话:<canvas> is a new HTML element which can be used to draw graphics using scripting (usuallyJavaScript). It can for instance be used to draw graphs, m...  阅读全文
posted @ 2010-05-20 09:41 暗夜教父 阅读(2184) | 评论 (0)编辑 收藏
在计算机领域,堆栈是一个不容忽视的概念,但是很多人甚至是计算机专业的人也没有明确堆栈其实是两种数据结构。 
堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。 
要点: 
堆:顺序随意 
栈:后进先出(Last-In/First-Out) 
编辑本段堆和栈的区别 
一、预备知识—程序的内存分配 
一个由c/C++编译的程序占用的内存分为以下几个部分 
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后由系统释放。 
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放 。 
5、程序代码区—存放函数体的二进制代码。 
二、例子程序 
这是一个前辈写的,非常详细 
//main.cpp 
int a = 0; 全局初始化区 
char *p1; 全局未初始化区 
main() 

int b; 栈 
char s[] = "abc"; 栈 
char *p2; 栈 
char *p3 = "123456"; 123456\0在常量区,p3在栈上。 
static int c =0; 全局(静态)初始化区 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); 

分配得来得10和20字节的区域就在堆区。 
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 
编辑本段堆和栈的理论知识 
1.申请方式
stack: 
由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间 
heap: 
需要程序员自己申请,并指明大小,在c中malloc函数 
如p1 = (char *)malloc(10); 
在C++中用new运算符 
如p2 = new char[20];//(char *)malloc(10); 
但是注意p1、p2本身是在栈中的。 
2.申请后系统的响应 
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。 
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。 
3.申请大小的限制 
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。 
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。 
4.申请效率的比较 
栈由系统自动分配,速度较快。但程序员是无法控制的。 
堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便. 
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈,而是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活 
5.堆和栈中的存储内容 
栈: 在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。 
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。 
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。 
6.存取效率的比较
char s1[] = "aaaaaaaaaaaaaaa"; 
char *s2 = "bbbbbbbbbbbbbbbbb"; 
aaaaaaaaaaa是在运行时刻赋值的; 
而bbbbbbbbbbb是在编译时就确定的; 
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。 
比如: 
#include 
void main() 

char a = 1; 
char c[] = "1234567890"; 
char *p ="1234567890"; 
a = c[1]; 
a = p[1]; 
return; 

对应的汇编代码 
10: a = c[1]; 
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] 
0040106A 88 4D FC mov byte ptr [ebp-4],cl 
11: a = p[1]; 
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] 
00401070 8A 42 01 mov al,byte ptr [edx+1] 
00401073 88 45 FC mov byte ptr [ebp-4],al 
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。 
7.小结: 
堆和栈的区别可以用如下的比喻来看出: 
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。 
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。 
编辑本段堆和栈的区别主要分: 
操作系统方面的堆和栈,如上面说的那些,不多说了。 
还有就是数据结构方面的堆和栈,这些都是不同的概念。这里的堆实际上指的就是(满足堆性质的)优先队列的一种数据结构,第1个元素有最高的优先权;栈实际上就是满足先进后出的性质的数学或数据结构。 
虽然堆栈,堆栈的说法是连起来叫,但是他们还是有很大区别的,连着叫只是由于历史的原因。
 
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
接下来主要讲 symbian 中的应用
 不管是在堆栈还是堆,对象都有自己的生命期,具体如下: 
  1、给对象分配内存[堆栈或者堆] 
  2、初始化:也就是给对象所在的内存赋值 
  3、使用对象 
    4、清除:释放对象使用的各种资源 
  5、释放对象所占的内存[从堆栈或者堆] 
  对象的生存期是一个基础概念。在某些操作系统,它是可以忽略的,因为程序中止的时候,堆栈和堆都会被销毁。但是在Symbian平台,程序往往需要能运行数个月。这就是为什么对象在生命期结束的时候就必须马上清除所有内存是那么重要的原因,不管它们分配在堆栈还是堆,不管它们生命期的结束是因为正常处理还是因为错误。 
Lifetimes in C 略 
Lifetimes in C++ 略 
Lifetimes in the Symbian platform
posted @ 2010-05-17 14:53 暗夜教父 阅读(541) | 评论 (0)编辑 收藏
     摘要: 转自http://blog.csdn.net/summerfang/archive/2006/05/20/746219.aspx很长时间里,我对“你什么时候会为PHPUnit写一个文档”这个问题的回答是:“你不需要PHPUnit文档,去读读JUnit文档或买一本Junit的书,试一试用PHP和PHPUnit来重写Java和Junit的例子”。当我和O...  阅读全文
posted @ 2010-04-13 19:30 暗夜教父 阅读(469) | 评论 (0)编辑 收藏

转自http://blog.csdn.net/summerfang/archive/2006/05/20/746216.aspx

聪明的Web开发人员会告诉你,越快找到代码的错误,你就能越快修正它,长期而言,项目成本越低。好了,能最有效的检测PHP代码中的错误的工具是PHPUnit,一个开发源代码的框架,它在你不在的时候,自动进行成套的单元测试。使用PHPUnit的好处是显而易见的:

l         减少用于测试代码的工作量

l         减少总体软件缺陷

l         增加对代码的信心

l         改善你和开发源代码的团队伙伴的关系

直到现在,这个流行工具唯一的问题是缺乏文档。为了解决这个问题,O’Reilly直接找到了源头,PHPUnit口袋书指南的作者,也是PHPUnit的创造者,Sebastian Bergmann,来解决这个问题。这本书把很多难以记忆的信息,语法,PHPUnit工作的原则,统一到一起。它也带来了只有技术创造者才能提供的洞察力和睿智忠告。而且,本书也谈到了敏捷方法和极限编程中关于测试的内容。

O’Reilly口袋书指南最近的系列中,这本快速参考书把所有的答案都带到了你的指尖。那些对测试PHP代码感兴趣的Web应用程序开发者,会觉得本书是一个无价的伴侣。

 

--------------------------------------------------------------------------------------------------------------

原文:

Overview

Smart web developers will tell you that the sooner you detect your code mistakes, the quicker you can fix them, and the less the project will cost in the long run. Well, the most efficient way to detect your mistakes in PHP is with PHPUnit, an open source framework that automates unit testing by running a battery of tests as you go. The benefits of PHPUnit are significant:

 

a reduction in the effort required to frequently test code

fewer overall defects

added confidence in your code

improved relations with your open source teammates

 

 

 

The only problem with this popular testing tool was its lack of documentation-until now, that is. For this, O'Reilly went right to the source, as Sebastian Bergmann, the author of PHPUnit Pocket Guide, also happens to be PHPUnit's creator. This little book brings together hard-to-remember information, syntax, and rules for working with PHPUnit. It also delivers the insight and sage advice that can only come from the technology's creator. Coverage of testing under agile methodologies and Extreme Programming (XP) is also included.

 

The latest in O'Reilly's series of handy Pocket Guides, this quick-reference book puts all the answers are right at your fingertips. It's an invaluable companion for anyone interested in testing the PHP code they write for web applications.

posted @ 2010-04-13 19:27 暗夜教父 阅读(306) | 评论 (0)编辑 收藏
     摘要: Flex ant tasks 提供了一种方便的手段使用工业标准级的构建工具来编译你的Flex工程。(The Flex Ant tasks provide a convenient way to build your Flex projects using an industry-standard build management...  阅读全文
posted @ 2010-04-12 15:08 暗夜教父 阅读(1686) | 评论 (0)编辑 收藏
对VS.NET工程进行自动构建工作使用什么?也许大家会异口同声的说是NANT。嗯,NANT无疑是自动构建VS.NET工程最快捷的工具,但对于一个拥有多个编程语言环境的项目,使用专用版的ANT工具却并不是一个好的解决方案,试想,如果你的项目拥有多个由不同语言开发的模块,那么你可能会同时使用ANT、WANT、NANT来分别管理特定的模块。
当然,这不是我们想看到的,同时维护三个构建工具实在不是什么明智之举(当然,如果你喜欢,那就无可厚非了),其实ANT已经为我们通吃所有语言环境准备好了精兵良驹。
ANT的exec标签是用来执行一个系统命令,这样我们就可以使用开发工具的命令行编译方法来完成相应项目的自动构建工作。下面我们只介绍VS.NET工程的命令行编译方法:
VS.NET开发工具的命令行编译命令是devenv,当然前提是将VS.NET的IDE目录路径放置到PATH变量中。设置好PATH变量,在控制台中键入devenv /?,我们可以看到VS.NET的各个参数说明,如下:

Microsoft (R) 开发环境 7.10.3077 版。
版权所有(C) Microsoft Corp 1984-2001。保留所有权利。
 
用法:
devenv [solutionfile | projectfile | anyfile.ext] [switches]
 
可以调用 devenv,用第一个参数指定解决方案文件或项目文件。
也可以调用 devenv,使第一个参数作为要在编辑器中打开的任何
其他类型的文件。如果提供项目文件,IDE 将通过在与项目文件
相同的目录中查找与项目文件具有相同基名称的 .sln 文件,在
解决方案的上下文中打开该项目文件。如果存在 .sln 文件,则
IDE 将查找引用该项目的单个 .sln 文件。如果不存在这样的单
 .sln 文件,则 IDE 将创建一个具有默认 .sln 文件名的未保
存的解决方案,而该默认文件名与项目文件具有相同的基名称。
 
命令行生成:
devenv solutionfile.sln /build solutionconfig [ /project projectnameorfile [ /p
rojectconfig name ] ]
 
可用的命令行开关:
 
/build          生成指定的解决方案配置
/project        指定生成项目而不是解决方案
                必须指定 /build 才能使用 /project
/projectconfig 指定要生成的项目配置
                必须指定 /project 才能使用 /projectconfig
/out            将生成结果写入指定的文件
/rebuild         /build 类似,但先执行强制清理
/clean          清理生成结果
/deploy         生成指定的解决方案配置然后部署它
/run            运行指定的解决方案配置
/runexit        运行指定的解决方案配置然后终止
/command        启动后执行指定的内部命令行
/mditabs        使用选项卡式文档界面
/mdi            使用 MDI 界面
/fn             使用指定的字体名称
/fs             使用指定的字体大小
/LCID           使用指定的语言 ID
/noVSIP         禁用用于 VSIP 测试的VSIP 开发人员许可证密钥
/safemode       出于稳定性仅加载默认的环境和服务
/resetskippkgs 允许曾被标记为加载失败的 VsPackages
                再次加载
/migratesettings 迁移另一个版本中的某些用户设置
 
产品特定的开关:
 
/debugexe       打开要调试的指定可执行文件。
                命令行的其余部分作为它的参数
                传递到此执行文件。
/useenv         使用 PATHINCLUDELIBPATH  LIB 环境变量
                而不是使用 VC++ 生成的 IDE 路径。
 
若要从命令行附加调试器,请使用:
        vs7jit.exe -p <pid>

可见VS.NET工具为我们提供了诸多支持命令行编译的参数,那接下来我们就开始动手配置Build.xml文件吧,为了节省篇幅,我这里只给出compile任务的代码:

1    <target name="compile" depends="init">
2        <mkdir dir="${pdcu}"/>
3        <echo message="Compiling application main source..."/>
4                 <delete file="${infofile}"/>        
5        <exec dir="${pdir}\" executable="devenv" os="${build.os}" >
6             <arg line=" ${pname}.sln
7                                   /rebuild
8                                   release     
9                                   /useenv
10                                 /out ${infofile}
11                                 "/>
12       </exec>
13     <echo message="Compiling application main source complete."/>
14 <loadfile property="compiled-info"
15            srcFile="${infofile}"/>
16        <echo message="${compiled-info}"/>       
17 <condition property="compile-success">
18      <and>
19       <contains string="${compiled-info}" substring="0 已失败"/>
20      </and>
21    </condition>
22 <fail unless="compile-success"
23        message="${compiled-info}"/>
24    </target>

我们来详细分析一下上面的代码。
第1行是任务定义,在此不过多解释。
2-4行是任务定义和准备工作,主要是建立编译生成目录和清理旧的输出文件。
5-12行便是命令行编译的主要代码,我们来逐个解释。
第5行定义了一个exec标签,用来调用devenv命令,并指定了编译所在当前目录dir属性,和操作系统信息os属性。
从第6行开始则为devenv命令的参数部分。
其中第6行指定了要编译的解决方案。
第7行标明该解决方案要进行重新编译。
第8行指定了编译类型为release模式。
第9行指定编译器使用 PATH、INCLUDE、LIBPATH 和 LIB 环境变量。
第10行指定了编译信息输出的文件位置。由于devenv命令执行完毕后,ANT无法从命令行获取编译信息,所以不能使用exec的output属性来指定输出位置(在调用Delphi编译器的时候,ANT可以正常获取编译信息,因此output属性有效),只能使用编译器所具有的参数功能将信息输出,该信息为判断编译成功与否的关键。
14-15行读取了上述的编译信息文件的内容,以便之后判断编译是否成功。
17-21行则定义了一个编译结果,用于判断编译是否成功。结果使用了contains属性来判断,如果输出文件中包含字符串“0 已失败”,则说明编译成功完成。
22-23行则是指示了ANT,一旦编译失败,则打印出编译信息。
当然,这里只介绍了编译VS.NET工程的其中一种方法,在此抛砖引玉。既然ANT为我们提供了如此强大的系统命令执行功能,那么我们便可以在各种编程语言环境中游刃有余了。
posted @ 2010-04-09 16:39 暗夜教父 阅读(514) | 评论 (0)编辑 收藏

一、简介:
  现在我们安装Linux的时候通常考虑到安全因素(默认情况下)是不打开telnet服务的,而ssh服务是有的,ant很早就支持telnet,但要求我们在Linux下要安装telnet-server,并要启用该服务。

还好自Ant1.60开始支持了SSH 及SCP 操作了,早在Ant之前若要支持SSH、SCP、SFTP等任务就必须下载j2ssh的j2ssh-ant.jar和j2ssh-core.jar(在http://www.sourceforge.net的j2ssh下有下载)。现在可以使用Ant提供的Sshexec和scp任务,由$ANT_HOME/lib/ant-jsch.jar提供支持,但是同样你也要在http://www.jcraft.com/jsch/index.html下载一个依赖包jsch-0.1.24.jar(文件名因版本而不同),jsch同样也是http://www.sourceforge.net下的一个项目。

你需要把下载的jsch-0.1.24拷贝到$ANT_HOME/lib下,如果是Eclipse下的Ant环境必须在Window->Preferences->Ant->Runtime->Classpath中加入jsch-0.1.24。

JSch是一个SSH2的纯Java实现
JSch允许你连接到sshd server并采用端口映射, X11 映射; Scp文件传输等,你可以把集成JSch提供的功能到你自己的Java项目中,JSch 的授权方式为 BSD形式。

二、简单例子:
  下面是用JSch完成Sshexec和scp两个任务的最简单例子,如果需要更详细的内容,请参考Ant用户手册

[Sshexec任务]
<BR><target name="sshexec">
      <sshexec host="192.168.122.180" username="root"  password="123456"
         trust="true" command="cd /;ls"/>
</target>

注意上面的trust属性一般设置为true, 如果为默认值false时,那么就要求你所连接的host必须存在于你的knownhosts文件中,并且这个文件也必须是存在的,否则会出现 com.jcraft.jsch.JSchException: reject HostKey: 192.168.122.180异常。执行Linux下的命令时可以用分号";"把多个命令隔开,它们将会依次执行,而不需要写多个sshexec进行多次连接,每次连接只执行一个命令。

该任务的执行后输出结果如下:

sshexec:
  [sshexec] Connecting to 192.168.122.180:22
  [
sshexec] backup
  [
sshexec] bin
  [
sshexec] boot
  [
sshexec] dev
  [
sshexecetc
  ...................

[scp任务]

1.拷贝单个文件到远端服务器
<scp file="c:/cmd.txt" todir="root:123456@192.168.122.180:/tmp" trust="true"/>

<scp file="c:/cmd.txt" todir="root@192.168.122.180:/tmp" password="123456" trust="true"/>

2.拷贝远端文件本地
<scp file="root:123456@192.168.122.180:/tmp/cmd.txt" todir="D:/my-app"  trust="true"/>

3.拷贝远端目录到本地,将以递归形式操作
<scp file="root:123456@192.168.122.180:/tmp/*" todir="d:/my-app" trust="true"/>

4.拷贝本地目录中的内容到远端,递归形式,但不在服务器上建立my-app目录
<scp todir="root:123456@192.168.122.180:/tmp/" trust="true">
   
<fileset dir="d:/my-app"/>
</scp>

5.拷贝一系列的文件到远端,会建立相应的层次目录,不建立my-app目录
<scp todir="root:123456@192.168.122.180:/tmp" trust="true">
   
<fileset dir="d:/my-app">
      
<include name="**/*.java" />
   
</fileset>
</scp>

<scp todir="root:123456@192.168.122.180:/tmp" trust="true">
   
<fileset dir="d:/my-app" excludes="**/*.java"/>
</scp>

最后一个任务的执行输出结果如下(其他略):

scp:
      [scp]Connecting to 192.168.122.180:22
      [
scp] Sending: cmd.txt : 0
      [
scp] File transfer time: 0.0 Average Rate: ? B/s
      [
scp] Sending: pom.xml : 852
      [
scp] File transfer time: 0.0 Average Rate: ∞ B/s
      [
scp] Sending: application.properties : 142
      [
scp] File transfer time: 0.0 Average Rate: ∞ B/s
      [
scp] Sending: application.properties : 45
      [
scp] File transfer time: 0.0 Average Rate: ∞ B/s
      [
scp] Sending: test.properties : 0
      [
scp] File transfer time: 0.02 Average Rate: 0.0 B/s
      [
scp] Sending: application.properties : 153
      [
scp] File transfer time: 0.0 Average Rate: ∞ B/s
      [
scp] Sending: application.properties : 45
      [
scp] File transfer time: 0.0 Average Rate: ∞ B/s
      [
scp] done.

三、其他例子:

例子1:
<?xml   version= "1.0 "?> 
<project   name= "buildssh "   default= "DEFAULT "   basedir= ". "> 
<target   name= "init "> 
<!--   set   properties,   mkdir,   etc.   --> 
<property   file= "build.properties "   /> 
<property   name= "this.project "   value= "buildssh "   /> 
<echo   message= "init   in   ${this.project} "   /> 
<tstamp   /> 
</target> 

<target   name= "DEFAULT "   depends= "init "> 
<echo   message= "connecting   to   ${build.server} "   /> 
<sshexec   host= "Linux   server   IP   address "   username= "Linux   server     username "   password= "Linux   server   password "   trust= "true "   command= "Command   you   want   to   run   on   the   server "   /> 
</target> 
</project>

例子2:
import   com.jcraft.jsch.Channel;       
import   com.jcraft.jsch.ChannelSftp;       
import   com.jcraft.jsch.JSch;       
import   com.jcraft.jsch.Session;       
import   com.jcraft.jsch.UserInfo;       
    
public   class   ExecSCP   {       
        public   static   final   UserInfo   defaultUserInfo   =   new   UserInfo(){       
                public   String   getPassphrase()   {       
                        return   null;       
                }       
    
                public   String   getPassword()   {       
                        return   null;       
                }       
    
                public   boolean   promptPassword(String   arg0)   {       
                        return   false;       
                }       
    
                public   boolean   promptPassphrase(String   arg0)   {       
                        return   false;       
                }       
    
                public   boolean   promptYesNo(String   arg0)   {       
                        return   true;       
                }       
    
                public   void   showMessage(String   arg0)   {       
                }       
        };       
    
        /**     
          *   @param   args     
          */     
public   static   void   main(String[]   args)   throws   Exception{ 
String   hostname   =   "www.mozat.com "; 
String   username   =   "wiimii "; 
String   password   =   "jtev000 "; 
String   remoteFile   =   "Setup.ini "; 
String   localFile   =   "C:\\ "; 

                JSch   jsch=new   JSch(); 

                Session   session=jsch.getSession(username,   hostname,   990); 
                session.setPassword(password); 
                session.setUserInfo(defaultUserInfo); 
                session.connect(); 

                Channel   channel=session.openChannel( "sftp ");       
                channel.connect();       
                ChannelSftp   c=(ChannelSftp)channel;       
                      
                c.get(remoteFile,   localFile);   
                
                session.disconnect(); 
              } 

posted @ 2010-04-09 16:29 暗夜教父 阅读(2819) | 评论 (0)编辑 收藏

这段ant脚本主要作用就是:自动从SVN库拉最新的代码,编译、并自动部署到测试服务器。

 

其中用到了“antsvn” ,有3个jar包需要配置进去


<?xml version="1.0" encoding="UTF-8"?> <!-- wei.songw 2008.3.19 --> <project basedir="." name="smmail" default="auto"> <!-- all properties are in build.properties --> <property file="build.properties" /> <!--svn本身需要的运行库 --> <path id="svnant.lib"> <pathelement location="${svnjavahl.jar}" /> <pathelement location="${svnant.jar}" /> <pathelement location="${svnClientAdapter.jar}" /> </path> <!--java EE 1.4 库 --> <path id="javaEE1.4"> <fileset dir="${javaEE1.4.lib}"> <include name="**/*.jar" /> </fileset> </path> <!--项目的classpath库 --> <path id="project.classpath"> <pathelement location="${build.dir}" /> <fileset dir="${lib.dir}" /> </path> <!--清理项目任务(干掉下载目录,tomcat原来的部署文件) --> <target name="clear"> <delete dir="${work.space}" /> <delete dir="${tomcat.home}/work/Catalina/localhost/${ant.project.name}" /> <delete dir="${tomcat.home}/webapps/${ant.project.name}" /> <delete dir="${tomcat.home}/webapps/${ant.project.name}.war" /> </target> <!-- load the svn task --> <taskdef name="svn" classname="org.tigris.subversion.svnant.SvnTask" classpathref="svnant.lib" /> <!--svn同步任务--> <target name="svn" depends="clear"> <mkdir dir="${work.space}"/> <svn username="SongWei" password="Song" javahl="false"> <checkout url="${urlRepos}" destPath="${work.space}" /> </svn> </target> <!--编译--> <target name="compile" depends="svn" description="======compile project======"> <echo message="compile==========>${ant.project.name}: ${ant.file}" /> <mkdir dir="${build.dir}" /> <copy includeemptydirs="false" todir="${build.dir}"> <fileset dir="${java.source}" excludes="**/*.launch, **/*.java, config/*.*"/> </copy> <copy includeemptydirs="false" todir="${build.dir}"> <fileset dir="${java.config}" excludes="**/*.launch, **/*.java"/> </copy> <javac includejavaruntime="true" debug="true" debuglevel="${debuglevel}" destdir="${build.dir}" source="${source}" target="${target}" encoding="utf-8"> <src path="${java.source}" /> <exclude name="config/"/> <classpath> <path refid="project.classpath"> </path> <path refid="javaEE1.4"> </path> </classpath> </javac> <javac debug="true" debuglevel="${debuglevel}" destdir="${build.dir}" source="${source}" target="${target}" encoding="utf-8"> <src path="${java.config}" /> </javac> </target> <!--压缩,打包--> <target name="war" depends="compile" description="======compress j2ee war file======"> <mkdir dir="${dist.dir}" /> <!--compress j2ee war file--> <war destfile="${war.file}" webxml="${web.dir}/WEB-INF/web.xml"> <fileset dir="${web.dir}" /> <classes dir="${build.dir}" /> <lib dir="${lib.dir}" /> </war> </target> <!--shutdowntomcat--> <target name="shutdowntomcat" description="========shutdowntomcat==========="> <exec executable="${tomcat.home}/bin/shutdown.sh" failonerror="false"></exec> <sleep seconds="10"/> </target> <!--startuptomcat--> <target name="startuptomcat" description="========startuptomcat==========="> <sleep seconds="5"/> <exec executable="${tomcat.home}/bin/startup.sh" failonerror="false"></exec> </target> <!--部署到tomcat下面克--> <target name="deploy" depends="war"> <copy file="${war.file}" todir="${tomcat.home}/webapps" /> </target> <!--全自动无敌部署,启动关闭tomcat--> <target name="auto" depends="shutdowntomcat,deploy,startuptomcat"> <echo message="DONE!!!!" /> </target> </project>


下面是build.xml指定的properties文件,需要和build.xml放在同一个目录下面

需要指定work.space(svn拉下来代码的存放,已经编译,打包用的临时目录)

tomcat.hometomcat服务器的根目录,如果是其他服务器,需要修改对应项

===============================================

build.version=1.0.0

svnant.jar=/usr/java/svn/svnant.jar
svnClientAdapter.jar=/usr/java/svn/svnClientAdapter.jar
svnjavahl.jar=/usr/java/svn/svnjavahl.jar
javaEE1.4.lib=/usr/javaEE-1.4

debuglevel=source,lines
target=1.6
source=1.6

work.space=/home/gmail/workspace
dist.dir=${work.space}

build.dir=${work.space}/WebRoot/WEB-INF/classes
lib.dir=${work.space}/WebRoot/WEB-INF/lib

java.source=${work.space}/src
java.config=${work.space}/src/config

web.dir=${work.space}/WebRoot
resource.dir=${work.space}/resources

tomcat.home=/home/gmail/tomcat6
war.file=${dist.dir}/${ant.project.name}.war

urlRepos=svn://192.168.1.100/product/SMMAIL/Develop

posted @ 2010-04-09 11:23 暗夜教父 阅读(1804) | 评论 (0)编辑 收藏
摘要:
  Subversion是越来越被广泛使用的版本管理工具,使用Ant脚本从Subversion获取代码,实现Daily Build。
  1.Subversion概述
  先引用Version Control with Subversion 中开头的话:
  “If C gives you enough rope to hang yourself, think of Subversion as a sort of rope storage facility.” 
   —Brian W. Fitzpatrick
  然后告诉大家CVS是旧爱,Subversion是新欢。列举若干Subversion的特性和优势为证,懒得写了,直接看这里:Subversion的老家
  关于如何使用Subversion以及相关客户端软件,网上慢慢看吧,官方自由图书不错。
  2.蚂蚁出场
  团队最近的项目中即使用Subversion作为版本控制工具。Daily Build过两天就得搭建起来了,上蚂蚁!
  Tigris.org提供了Subclipse,SvnClientAdapter和SvnAnt。(见这里)
  Subclipse是一个Eclipse的插件,实现了IDE与Subversion得集成;
  SvnClientAdapter是Subversion的一套Java API,封装了客户端对Subversion的一些访问操作;
  SvnAnt是用于访问Subversion的Ant任务,其依赖于SvnClientAdapter。
  我要用的就是SvnAnt,用SVN Check Out一份SvnAnt的代码:
   
   
   
   
   svn co http://subclipse.tigris.org/svn/subclipse/trunk/svnant/ svnant
   
   
   
   
  在这个工程里面还包括svnant的Ant Task使用说明文档,也可以在这里直接查看。
  使用其中的build.xml编译SvnAnt后,在新生成的build子目录下会生成svnant.jar。按照官方文档的说法,把这个svnant.jar和SvnAnt工程的lib目录下的svnClientAdapter.jar和svnjavahl.jar拷贝到Ant的目录下即可。然后编写如下的Ant脚本进行测试:
   
   
   
   
   <?xml version="1.0"?>
   <project name="SVN Ant Test" default="checkout" basedir=".">
   <!-- 1 -->
   <property name="remote.url"
   value="svn://16.157.xxx.xxx/trunk/LNPORTAL/src/P3UIPAdapter/" />
   <property name="local.dir" value="local" /> 
   <!-- 2 -->
   <taskdef name="svn" classname="org.tigris.subversion.svnant.SvnTask" />
   <target name="prepare"
   description="Prepare the dirs for other tasks">
   <delete dir="${local.dir}" />
   <mkdir dir="${local.dir}" />
   </target>
   <!-- 3-->
   <target name="checkout" depends="prepare">
   <svn javahl="true" username="lihq" password="password" >
   <checkout url="${remote.url}" destPath="${local.dir}" />
   </svn>
   </target>
   </project>
   
   
   
   
  测试结果暂时不重要。
  3.JavaSVN出场
  SvnAnt的执行依赖SvnClientAdapter,而执行访问SVN时又有两种形式:其一是通过SVN 命令行程序的形式进行的(我在想:如果是这样,还不如使用Ant的exec任务呢);其二是通过Javahl来执行的。
  Javahl是一个用于访问Subversion的Java接口(估计是JNI),这需要Windows机上有svnjavahl.dll才行。团队的Daily Build的并不是Windows,于是求助JavaSVN,这是一个纯Java的SVN解决方案。
  请访问这个Guide:Making SvnAnt use JavaSVN
  我的实际步骤如下:
  Step 1:从Ant的lib目录下移除SvnClientAdapter.jar,我没有发现javahl.jar,于是便移除了svnjavahl.jar,其实移不移后者无所谓;
  Step 2:在刚才那个页面下载javasvn.jar和javasvn-javahl.jar,以及JavaSVN的svnClientAdapter-0.9.32.jar。并把这三个jar都拷贝到Ant的lib目录下;
  然后运行上面写的SVN Ant测试脚本,结果如下:
   
   
   
   …
   BUILD FAILED
   java.lang.AbstractMethodError: org.tigris.subversion.svnant.Feedback.logRevision(J)V
   
   Total time: 7 seconds
   
   
   
  虽然SVN的代码都取下来了,但最后Ant会抛出一个如上的错,这会使得Ant脚本无法运行后面的任务。
  4.Thanks Open Source
  看来,大概是JavaSVN用自己的svnClientAdapter-0.9.32.jar改变了SVNAnt本来对调用。SVNAnt(by Tigris.org)原先是调用svnjavahl.jar来运行SVN命令的。替换svnClientAdapter-0.9.32.jar后,SVNAnt(plus JavaSVN)是调用javasvn-javahl.jar和javasvn.jar来运行SVN命令的。上面那个错误大概就是两套svnClientAdapter对某个抽象方法的定义不完全一致造成的,估计是API版本对应的问题。解决如下:
  首先查看svnant.jar的源代码,发现org.tigris.subversion.svnant.Feedback是实现svnClientAdapter.jar中的一个名为ISVNNotifyListener的接口。这个接口中对报错的logRevision方法的定义是:
   
   
   
   
   public abstract void logRevision(long revision, String path)
   
   
   
   
  而查看svnClientAdapter-0.9.32.jar中的ISVNNotifyListener的接口中的定义是:
   
   
   
   
   public abstract void logRevision(long revision)
   
   
   
   
  明显不匹配,于是修改svnant.jar的源代码,修改org.tigris.subversion.svnant.Feedback,象其中添加一个方法如下:
   
   
   
   
   //This method is added by Beegee
   public void logRevision(long revision) {
   }
   
   //This method is the original one by SVNANT
   public void logRevision(long revision, String path) {
   }
   
   
   
   
  然后重新编译SVNAnt,生成svnant.jar,拷贝替换Ant 的lib目录下的同名jar,重新运行以上SVN Ant测试脚本,结果如下:
  

  OK!
  -end-
posted @ 2010-04-09 11:20 暗夜教父 阅读(499) | 评论 (0)编辑 收藏
仅列出标题  下一页

<2010年4月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

常用链接

留言簿(2)

随笔分类

随笔档案

文章分类

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜