雨中的阳光Seattle

靠着很近的Redmond

[转] Code Review流程工具Jupiter介绍 2010年04月5日

Filed under: Uncategorized — systembug @ 1:22 上午

 

http://rdc.taobao.com/blog/qa/?p=3066

引言
Code Review的作用和意义已在很多技术团队内达成共识,可是很多时候并未被有效执行,甚至被认为是一项费时费力的工作。借助一些工具可以更容易,更有效率地来进行Code Review,本文介绍的Jupiter即是其中之一。
Jupiter概述
Jupiter是一款开源的Eclipse插件,以XML形式存储review数据,通过SVN/CVS将review结果在团队内共享。一个很方便的功能是其建立了review问题跟具体源代码的对应关系(通过点击review问题列表中的问题可以跳转到对应的代码段,通过点击代码段上的review问题标记可对应到具体的问题描述),review问题列表支持各种filter规则(根据review问题状态、责任人等,通过这个filter可以列出具体阶段需关注的问题)。
Jupiter安装
通过Eclipse的update site 在线安装:http://jupiter-eclipse-plugin.googlecode.com/svn/trunk/site/
或下载后安装:http://code.google.com/p/jupiter-eclipse-plugin/downloads/list
安装后可能需重启Eclipse。
Jupiter的Code Review流程
Jupiter的Code Review流程为以下几步:
1.建立review任务:代码修改者或TL建立review任务,指定需评审的代码文件、参与评审的人员、定义问题类型及严重级别等。
2.个人评审阶段:开始个人独自评审,将可能出现的问题加入问题列表。
3.团队评审阶段:团队成员坐在一起,讨论个人评审阶段的问题,确定是否需要修复并分配解决人员。
4.问题修复阶段:每个人修复分配给自己的问题,修复后修改问题状态。
下面图文介绍具体的操作(点击图片看大图)。
1.建立review任务
在“Package Explorer”或“Navigater”里,右键点击项目名称,选择“Properties”显示项目属性窗口。

选择“Review”将显示Jupiter属性

点击“New”按钮打开新建Review ID对话框,输入Review ID(需符合文件命名规则)和Description。

选择需要Review的文件,可一次选择多个

需要Review的文件列表,可继续Add或选中后Remove

设置参加Review的人员,每次添加一个,重复多次

添加后的Reviewer列表,可继续Add或选中后remove

选择评审负责人

接下来的几步是设置问题类型及严重级别和filter,根据实际情况修改或用默认值,finish后会在工程根目录生成.jupiter文件,提交该文件到SVN。

2.个人评审阶段
从SVN上更新最新的源代码和.jupiter文件,在Eclipse里“Window”-“Open Perspective”-“Other”选择“Review”打开Review视图

选择“Individual Phase”

选择Project Name(项目名称),Review ID(review任务)和Reviewer ID(评审人员)

“Review Table”右边第一个下拉菜单显示了需Review的文件

选择文件就可以开始review了,发现问题时,光标停在问题代码处,点击鼠标右键选择“Add Review Issue……”

在“Review Editor”里选择问题类型及严重性,添加概要和详细描述,保存。可以看到增加了Review问题的代码会在行首处有标记。

个人评审完毕后将Jupiter评审数据目录(默认为review)下的数据上传到SVN。
3.团队评审阶段
团队成员坐在一起,从SVN上更新最新的Review数据,从review试图中选择“Team Phase”,点击“Review Table”中的问题会跳到对应的代码,一起讨论代码是否确实存在问题,在“Review Editor”里分配修复人员及解决方式,保存。

团队评审完毕后将Review数据上传到SVN。
4.问题修复阶段
个人回到自己的工作机,更新最新的review数据,从review试图中选择“Rework Phase”,会在“Review Table”里列出分配给自己的问题,逐一修复,并在“Review Editor”将问题状态改为“Resovled”,保存并将review数据上传到SVN。

Rework完成后,各位评审者再次检查,如果检查未通过,可将问题状态改为“Re-Opened”,确认问题修复后将问题状态改为“Closed”,
至此,一个Code Review流程结束。
参考资料:

http://code.google.com/p/jupiter-eclipse-plugin/wiki/UserGuide

 

[转] Maven2 的新特性 2010年04月3日

Filed under: Uncategorized — systembug @ 8:38 上午

http://www.ibm.com/developerworks/cn/opensource/os-maven2/

本文主要阐述 Maven2 的新特性,这些新特性可以大大地缩短了开发管理中的工作量,使得开发人员将精力集中在实际的业务问题上。

Maven 出现到现在也有很长时间了,初识它的感觉至今仍清晰的印在脑海中。现在想来,当时从 Ant 移情 Maven 的想法其实很朴素,就是因为 Maven 可以以网站的形式展现与项目相关的信息,如开发人员列表、各种 Report。这种方式为项目的构建带来了极大的方便,尤其是 Report 的。试想对于产生的 Junit-Report、JavaDoc、CheckStyle、PMD 等报告,如果没有一个统一的入口,每次切换目录是多么令人厌烦的事情!

Maven 无疑是相当成功的,这一点从越来越多的开源项目开始使用 Maven 就可以看出。Maven 取得成功的原因很简单:在简化构建脚本的同时,功能并没有缩水,反而有所增强;提供汇集项目信息的工具,并以相当友好的方式呈现;丰富的插件简化了工作。如此有力的工具出现,自然是争相使用。

新特性

如今 Maven2 已经推出,Maven 的官方网站称,Maven2 相对于 Maven1 是一个相当大的转变,甚至不惜牺牲兼容性来达到这一目的。(为了 Maven1 的用户着想,Maven1 仍在继续他的使命。)如此大的变动到底换来了什么样的结果?

1. 更快、更简单

比起 Maven1 那不急不慢的运行速度,Maven2在速度上有了质的飞跃,甚至与Ant相比也毫不逊色(当然,下载不算)。除此之外,"简化工作,使用业界公认的最佳实践"也是是 Maven2 的另一大主题,其他的新特性无处不在体现 Maven2 为简化工作而做出的努力。

2. 更少的配置文件

Maven1 和 Maven2 主要配置文件的对比:

  • Maven1:project.xml、maven.xml、project.properties和build.properties。
  • Maven2:pom.xml和settings.xml。

POM是Maven的核心对象模型,在Maven2中POM已由project.xml转移到pom.xml中使用,版本也由3升级为4。对于项目,一般只需要pom.xml就行了。

在Maven2中不需要也不提倡使用maven.xml,原因如下:

  • plugin的易用性的增强。
  • 散布于maven.xml中的内容难以在不同项目间共享,也不利于维护。在Maven2中建议使用自定义的plugin来封装这些内容。

如果仍期望能够使用类似maven.xml的功能,如<preGoal>,请参考Inserting non-standard build steps using preGoals and postGoals。

在Maven2中,配置使用settings.xml,它取代了原有的project.properties和build.properties。配置在Maven2中存在两种级别:

  • 用户级,针对操作系统登录用户而言。一般在$home/.m2/,对于windows用户,就是目录:C:\Documents and Settings\用户名\.m2\settings.xml。
  • 全局级:一般在%M2_HOME%/conf/settings.xml,M2_HOME是Maven2的根目录环境变量名。

在settings.xml中可以配置,如本地Repository、proxy等等,关于settings.xml的结构可以从Maven的官方网站上获取。

3. Plugin语言更换

在Maven2中,编写plugin的语言由jelly变更为Java和BeanShell。Java在速度上更有优势,而且开发人员的熟悉程度更高。对于其他的流行脚本,如groovy,Maven的官方网站的意见是,等待其更成熟时再考虑

4. 提供预定义的目录模板

好的目录结构可以使开发人员更容易理解项目,为以后的维护工作也打下良好的基础。Maven2根据业界公认的最佳目录结构,为开发者提供了缺省的标准目录模板。Maven2的标准目录结构如下:

使用目录模板,可以使pom.xml更简洁。因为Maven2已经根据缺省目录,预定义了相关的动作,而无需人工的干预。以resources目录为例:

  • src/main/resources,负责管理项目主体的资源。在使用Maven2执行compile之后,这个目录中的所有文件及子目录,会复制到target/classes目录中,为以后的打包提供了方便。
  • src/test/resources,负责管理项目测试的资源。在使用Maven2执行test-compile之后,这个目录中的所有文件及子目录,会复制到target/test-classes目录中,为后续的测试做好了准备。

这些动作在 Maven1 中,是需要在 maven.xml 中使用<preGoal>或<postGoal>来完成的。如今,完全不需要在pom.xml中指定就能够自动完成。在src和test都使用resources,方便构建和测试,这种方式本就已是前人的经验。通过使用Maven2,使这个经验在开发团队中得到普及。

创建标准目录模板,可以通过如下命令:

mvn archetype:create -DgroupId=com.codeline.commons -DartifactId=codelineCommons

groupId和artifactId的含义与Maven1中的含义一样,参数artifactId的值会作为项目根目录的名字。除了建立相应的目录之外,Maven2还会创建缺省的pom.xml。

Maven2也考虑到:不同类型的项目需要拥有不同的目录结构。如创建web项目,可以使用命令:

mvn archetype:create -DgroupId=com.mycompany.app
-DartifactId=my-webapp
-DarchetypeArtifactId=maven-archetype-webapp

5. 生命周期的引入

在Maven2中有了明确的生命周期概念,而且都提供与之对应的命令,使得项目构建更加清晰明了。主要的生命周期阶段:

  • validate,验证工程是否正确,所有需要的资源是否可用。
  • compile,编译项目的源代码。
  • test-compile,编译项目测试代码。
  • test,使用已编译的测试代码,测试已编译的源代码。
  • package,已发布的格式,如jar,将已编译的源代码打包。
  • integration-test,在集成测试可以运行的环境中处理和发布包。
  • verify,运行任何检查,验证包是否有效且达到质量标准。
  • install,把包安装在本地的repository中,可以被其他工程作为依赖来使用
  • deploy,在整合或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。
  • generate-sources,产生应用需要的任何额外的源代码,如xdoclet。

如果要执行项目编译,那么直接输入:mvn compile即可,对于其他的阶段可以类推。阶段之间是存在依赖关系(dependency)的,如test依赖test-compile。在执行mvn test时,会先运行mvn test-compile,然后才是mvn test。

6. 新增Dependency Scope

在POM 4中,<dependency>中还引入了<scope>,它主要管理依赖的部署。目前<scope>可以使用5个值:

  • compile,缺省值,适用于所有阶段,会随着项目一起发布。
  • provided,类似compile,期望JDK、容器或使用者会提供这个依赖。如servlet.jar。
  • runtime,只在运行时使用,如JDBC驱动,适用运行和测试阶段。
  • test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。
  • system,类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它。

<scope>的使用举例:

<dependency>
<groupId>hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>

7. 传递依赖,简化依赖管理

在Maven1中,需要把依赖所需要的包也一并列出。这对于使用类似如Hibernate的用户来说所操的心太多了,而且也不方便。在Maven2中实现了传递依赖,如此对于Hibernate所依赖的包,Maven2会自动下载,开发人员只需关心Hibernate即可。

注意:只有得到Maven支持的依赖,通常是plugin形式出现,才能获得这个特性。而且对于一些老的plugin,可能由于时间的关系不支持传递依赖。如至少在Maven 2.0.1中,对于Hibernate 2.1.2,仍然需要显式列出Hibernate 2.1.2所依赖的包。



回页首

使用简介

安装Maven2的步骤非常简单:首先从Maven官方网站下载相应的软件包,目前是Maven 2.0.1;然后解压,并设置环境变量M2_HOME= Maven2的解压安装目录;最后将%M2_HOME%/bin添加到path中,方便Maven在任何目录下运行。

Maven2的运行命令是mvn,使用mvn -h可以获得相关的帮助信息。常用情形:

  • 创建Maven项目:mvn archetype:create
  • 编译源代码:mvn compile
  • 编译测试代码:mvn test-compile
  • 运行测试:mvn test
  • 产生site:mvn site
  • 打包:mvn package
  • 在本地Repository中安装jar:mvn install
  • 清除产生的项目:mvn clean

或许是由于刚刚推出的缘故,Maven2目前还是有一些不尽如人意的地方。尤其是Report部分的plugin,有的是因为目前还没有,如junit-report。有的则是一些莫名其妙的问题,如checktyle和pmd,在本地locale下都无法正常工作。以pmd举例,在产生PMD报告时会抛出如下异常:

java.util.MissingResourceException: Can't find bundle for base name pmd-report,
locale zh_CN
        at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle
.java:839)
        at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:808)
        at java.util.ResourceBundle.getBundle(ResourceBundle.java:702)
……

幸运的是,Maven2一出现就备受关注,要不了多长时间,诸如此类的问题应该就会很快解决。

 

Maven Build Lifecycle

Filed under: Uncategorized — systembug @ 8:35 上午

Maven 2是围绕着Build Lifecycle概念设计的。这意味着,构建或者发布的过程已经被清晰的定义了。
Build lifecycle是由a set有依次顺序的phases组成的。当我们使用Maven构建工程时,我们只需要了解自己希望做什么,然后执行对应的lifecycle phase即可。
例如,我们希望编译我们的工程,在命令行状态下进入到工程的pom.xml文件所在的目录中,使用命令:mvn compile;希望构建打包我们的工程,使用mvn package即可。
每个LifeCycle phase实质上都会绑定到某个plugin:goal上!!例如命令
mvn compile
实际上等价于
            mvn compiler:compile
即执行compile phase命令=执行compiler plugin的compile goal
但有一个很关键的知识点:pom.xml的<packaging>的值不同,会影响lifecycle phase与哪个plugin:goal的绑定。例如:
如果是
<packaging>jar</packaging>
那么
package phase绑定到jar:jar

            mvn package = mvn jar:jar
如果是
<packaging>war</packaging>
那么
package phase绑定到war:war

            mvn package = mvn war:war
在default lifecycle里,包含下列最常用被执行的phases(文章最后会给出lifecycle phases的完整列表):
validate : validate the project is correct and all necessary information is available
compile : compile all java files in project
test : 使用unit test framework来test the compiled source code。这些test class不会被packaged and deployed。
package : 把compiled code打包成你需要的格式,如JAR.
integration-test : 把已经打包的东东(如jar)deploy到运行环境内,用于集成测试
verify : run any checks to verify the package is valid and meets quality criteria
install : install the package into the local repository, 这样做的目的是作为其他projects的一个local dependency
deploy : 该phase会copy final package到remote repository for sharing。This phase is done in an integration or release environment。
另外还有3个很常用的、但不属于default lifecycle的phase:
clean : cleans up artifacts created by prior builds
site : generates site documentation for this project
eclipse:eclipse : 创建相关的eclipse ide文件  
当你执行一个phase命令时,maven就会执行顺序排在该phase之前的所有phases,然后再执行该phase。例如,如果我们执行“compile” phase,那么maven实际要执行的phases依次为:
1.       validate
2.       generate-sources
3.       process-sources
4.       generate-resources
5.       process-resources
6.       compile
一个mvn命令可以同时执行多个phases,如:
mvn clean install
该命令是先执行clean phase,然后执行install phase
<packaging>与lifecycle phase
pom.xml的<packaging>的值(缺省为)会直接影响mvn lifecycle phase的执行操作,即不同的值将直接影响lifecycle phase与哪个plugin:goal的绑定。
例:
1)如果是<packaging>jar</packaging>,那么lifecycle phases与plugin:goal的绑定为(左边为lifecycle phase,右边为实际操作plugin:goal):
process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
Test-compile compiler:testCompile
Test surefire:test
package jar:jar
install install:install
deploy deploy:deploy

看上面列表,其中最值得注意的是package phase绑定到了jar:jar上,
执行mvn package = mvn jar:jar
2)如果是<packaging>war</packaging>,那么package phase会绑定到war:war上,执行mvn package = mvn war:war
3)如果是<packaging>pom</packaging>,那么上面列表中只有“install” and “deploy”被绑定到,而其他phases则没有被绑定到。也就是说如果执行mvn package,则什么操作也没执行。
另外一个很重要的知识点是:有一些<packaging>值的使用,必须在pom.xml里添加相应的<plugin>配置信息。
例如:如果你要使用
<packaging>plexus-application<packaging>
or
<packaging>plexus-service<packaging>
就必须在pom.xml里添加“Plexus” plugin配置。
<plugin> 与lifecycle phase
<plugin> element可以给lifecycle phase添加要执行的goal,<plugin>设置的goal将会被添加到goal list goals which already bound to the lifecycle from the packaging selected。这时某个phase被绑定了1个以上的goal,那么在执行该phase的mvn命令时,会先执行<packaging>本身所绑定的goal,然后再执行<plugin>绑定的goals。你更可以使用<plugin>的child element <executions>来控制goal的执行顺序。
例:有一个Modello plugin,它总是绑定modello:java到generate-sources phase(注意:设置绑定不是在你的pom.xml里,而是plugin本身已经设置好了的!!)
如果你的project想使用Modello plugin来generate sources from a model,那么就需要在pom.xml里的<build>里的<plugins>里添加下列代码:

<plugin>
   <groupId>org.codehaus.modello</groupId>
   <artifactId>modello-maven-plugin</artifactId>
   <executions>
     <execution>
       <configuration>
         <model>maven.mdo</model>
         <modelVersion>4.0.0</modelVersion>
       </configuration>
       <goals>
         <goal>java</goal>
       </goals>
     </execution>
   </executions>
</plugin>

为什么要使用<executions>?这是因为使用它可以对同一个goal根据不同的<configuration>来执行多次。
如果有多个匹配某个phase的<execution>,那么他们将会被依次按顺序执行(当然,被继承的execution会先被执行)
我们再来考虑这样一种情况:上面提到Modello plugin的goal(modello:java)被绑定到generate-sources phase(注意:设置绑定不是在你的pom.xml里,而是plugin本身已经设置好了的!!),如果我还希望该goal能够同时也绑定到另外的、非内在绑定的phase上,怎么办呢?很简单,只需要在<execution>里使用<phase>来设置。例如,你有一个goal touch:timestamp,它是用来输出某个file的timestamp,该goal内在绑定到test phase,你希望能把它也绑定到process-test-resources上,则使用下列代码:

<plugin>
   <groupId>com.mycompany.example</groupId>
   <artifactId>touch-maven-plugin</artifactId>
   <executions>
     <execution>
       <phase>process-test-resources</phase>
       <configuration>
         <file>${project.output.directory}/timestamp.txt</file>
       </configuration>
       <goals>
         <goal>timestamp</goal>
       </goals>
     </execution>
   </executions>
</plugin>

lifecycle phases的完整列表(按执行的先后顺序)
validate validate the project is correct and all necessary information is available.
generate-sources generate any source code for inclusion in compilation.
process-sources process the source code, for example to filter any values.
generate-resources generate resources for inclusion in the package.
process-resources copy and process the resources into the destination directory, ready for packaging.
compile compile the source code of the project.
process-classes post-process the generated files from compilation, for example to do bytecode enhancement on Java classes.
generate-test-sources generate any test source code for inclusion in compilation.
process-test-sources process the test source code, for example to filter any values.
generate-test-resources create resources for testing.
process-test-resources copy and process the resources into the test destination directory.
test-compile compile the test source code into the test destination directory
test run tests using a suitable unit testing framework. These tests should not require the code be packaged or deployed.
prepare-package perform any operations necessary to prepare a package before the actual packaging. This often results in an unpacked, processed version of the package. (Maven 2.1 and above)
package take the compiled code and package it in its distributable format, such as a JAR.
pre-integration-test perform actions required before integration tests are executed. This may involve things such as setting up the required environment.
integration-test process and deploy the package if necessary into an environment where integration tests can be run.
post-integration-test perform actions required after integration tests have been executed. This may including cleaning up the environment.
verify run any checks to verify the package is valid and meets quality criteria.
install install the package into the local repository, for use as a dependency in other projects locally.
deploy done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.

Build lifecycle与plugin开发
开发Plugin简单来说就是开发一组“根据输入和输出参数来执行某些操作”的goals(也就是mojo),然后把goal绑定到相应的lifecycle phase上去。
Plugin通过3种方式来与lifecycle phase进行绑定:
绑定一个mojo到一个特定的phase上
定义一个packaging type(即定义一个pom.xml中<packaging>的值),并设置相应的lifecycle bindings
forking a parallel lifecycle
Binding a Mojo to a Phase
在mojo上添加annotation @phase来把mojo绑定到某个lifecycle phase上。如下面的annotation就是把mojo绑定到generate-sources phase上:
@phase generate-sources
这样,当MOJO对应的GOAL在POM.XML里有进行设置,那么该goal就会在绑定的phase里被执行。
定义一个packaging type(即定义一个pom.xml中<packaging>的值)
如果你的plugin希望提供一个特别的artifact type,也就是提供一个特别的<packaging>值,那么你不仅需要提供package phase要绑定的goal,还需要提供其他default lifecycle phases与goals的绑定。
定义packaging type是在plugin jar的META-INF/plexus/components.xml里。下面的例子是Plexus plugin在register一个packaging type:  plexus-application。
<component-set>
<components>
    <component>
      <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
      <role-hint>plexus-application</role-hint>
      <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
      <configuration>
        <phases>
          <process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
          <compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile>
          <process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
          <test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
          <test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
          <package>org.codehaus.plexus:plexus-maven-plugin:app</package>
          <install>org.apache.maven.plugins:maven-install-plugin:install</install>
          <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
        </phases>
      </configuration>
    </component>
</components>
</component-set>
在上面的代码中,
<role-hint>的值是新定义的packaging type。
<role>的值为org.apache.maven.lifecycle.mapping.LifecycleMapping,表示这是为packaging进行的lifecycle绑定。
<implementation> element是必须的,该例子是使用缺省的implementation.
<configuration> element里是为这个新定义的packaging type设置被绑定的phases list。列表中的每一个phase都会被绑定到一个goal上。请注意goal设置必须是"fully qualified"的(格式为:groupId:artifactId:goal or groupId:artifactId:version:goal)。
值得留意的是:上述代码只是把package phase绑定到自定义plugin的app goal上,其他phase还是绑定到缺省的goal上。
针对上面代码定义的packaging type “plexus-application”,如果你要在你的project里使用它,你的pom.xml应该类似于:

<packaging>plexus-application</packaging>

<plugin>
   <groupId>org.codehaus.plexus</groupId>
   <artifactId>plexus-maven-plugin</artifactId>
   <extensions>true</extensions>
</plugin>

注意:如果你使用自定义的artifact type handlers,那么就必须设置<extensions>。
One final task that is required is for the packaging goal you have created to tell Maven where to find what you built. This is done with code such as the following:
project.getArtifact().setFile( new File( "target/myFile-2.0.jar" ) );
如何定义一个Custom Artifact Handler
缺省的artifact handler会packaging, type, and file extension映射成相同的值。例如,如果你定义了一个packaging为“plexus-application”,那么在repository里对应的file为“myartifactId-1.0.plexus-application”。这个规则也适用于a particular type from a dependency.
如果你想修改extension, 或者想修改a dependency’s type field映射到其他fields的方式,你必须在你的plugin jar里的META-INF/plexus/components.xml里配置一个custom artifact handler。
下面代码是A complete artifact handler for the test-jar type:
<component-set>
<components>
    <component>
      <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
      <role-hint>test-jar</role-hint>
      <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
      <configuration>
        <classifier>tests</classifier>
        <extension>jar</extension>
        <type>test-jar</type>
        <packaging>jar</packaging>
        <language>java</language>
        <addedToClasspath>true</addedToClasspath>
      </configuration>
    </component>
</components>
</component-set>
The fields are configured as follows:
Field Required? Default Description
role-hint Y   The type being defined.
type Y   Must match the role-hint .
extension N The type The extension to give the artifact in the repository.
packaging N The type The packaging of the artifact to look for.
classifier N   The classifier to append to the artifact name (after version and before extension) when using this type.
language N java The language the artifact is written in. No set values – free text.
addedToClasspath N true Whether the artifact should be included in a classpath or library path when used.
includesDependencies N false If the artifact already includes all of its dependencies, this setting ensures they are not propogated transitively.

因此,只要该plugin被declare同时type被用到,如果使用custom artifact handler,就必须设置<extensions> element。
Forking a Parallel Lifecycle
While lots of mojos will participate in the standard lifecycle, there are just as many that are used in other scenarios. These are mojos that are executed standalone from the command line (such as idea:idea ), or individual reports in the site building process.
However, sometimes these goals require that a particular task has already been performed – for instance, the IDEA plugin must ensure sources have been generated to properly construct its module files. If the goal were participating in the lifecycle, it would easily do this by ensuring it occurred after the phase it depended on having run. Since this isn’t the case, it must have a way to first execute that task.
Additionally, even goals participating in the build lifecycle might need to perform a task with different parameters to what was already used, and does not want the output to affect the current build (for example, running clover:check to run tests with modified sources and fail if a certain coverage ratio is not achieved).
For these reasons, mojos are capable of forking a new lifecycle. The lifecycle will be a normal build lifecycle, a clone of the one currently being used (including any additional bindings from the POM), executed up until the point specified by the mojo.
For example, the idea:idea mojo specifies the following in the mojo level declarations to call the source generation:
@execute phase="generate-sources"
But what happens if generate-sources has already been run in this build? In the current version of Maven, there is no way to tell if the previous execution used the same input and outputs as the current mojo requires, so the task (and any preceding ones if from the lifecycle) must be run again.
For this reason, it is important that if your plugin does any intensive work, you should first check whether it is necessary to perform the tasks again, perhaps by using timestamp checking or a similar technique. As an example, the compiler plugin will only recompile changed source files so can very efficiently be run multiple times in a build if necessary.
When the lifecycle is forked, the project object being used is also cloned. In this way, modifications made to the project as part of the execution, such as the addition of a new source root, will not affect the original build. When the lifecycle finishes executing and control is passed to the original mojo, it can access that project using the expression $executedProject . For example:
/**
* @parameter expression="${executedProject}"
*/
private MavenProject executedProject;
This project instance can be used by the mojo to obtain results, and propogate any changes it sees fit into the original build.
Finally, when forking the new lifecycle, it is possible to augment it on top of the changes already made by the packaging and the plugins in the POM.
For example, consider the Clover plugin. If clover:check were to be run from the command line, the plugin would need to fork the lifecycle, executing the test phase. But, it would also need to add some configuration and bind the clover:compiler goal to the generate-sources phase.
This can be achieved by including the following file as META-INF/maven/lifecycle.xml in the plugin JAR:
<lifecycles>
<lifecycle>
    <id>clover</id>
    <phases>
      <phase>
        <id>generate-sources</id>
        <executions>
          <execution>
            <configuration>
              <debug>true</debug>
            </configuration>
              <goals>
                <goal>compiler</goal>
              </goals>
          </execution>
        </executions>
      </phase>
    </phases>
</lifecycle>
</lifecycles>
Here, the executions element is present in a similar way to a plugin declaration in the POM. This can be used to bind a goal one or more times to a particular phase, as well as specifying configuration. Note that configuration already provided in the POM to that plugin that is not part of a specific execution will also be applied.
The lifecycle ID given here (clover ) can then be used in the mojo to specify what to overlay on the forked lifecycle when executing it, using the following mojo level declaration:
@execute phase="test" lifecycle="clover"

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/totogogo/archive/2007/12/17/1942867.aspx