├── .gitignore
├── src
└── main
│ ├── resources
│ └── template
│ │ ├── seimi.cfg
│ │ ├── run.bat
│ │ └── run.sh
│ └── java
│ └── cn
│ └── wanghaomiao
│ └── maven
│ └── plugin
│ └── seimi
│ ├── TemplateTask.java
│ ├── WarInPlaceMojo.java
│ ├── overlay
│ ├── InvalidOverlayConfigurationException.java
│ ├── DefaultOverlay.java
│ └── OverlayManager.java
│ ├── packaging
│ ├── WarPackagingTask.java
│ ├── WarPostPackagingTask.java
│ ├── CopyUserManifestTask.java
│ ├── SaveWebappStructurePostPackagingTask.java
│ ├── ClassesPackagingTask.java
│ ├── OverlayPackagingTask.java
│ ├── WarPackagingContext.java
│ ├── ArtifactsPackagingTask.java
│ ├── DependenciesAnalysisPackagingTask.java
│ ├── WarProjectPackagingTask.java
│ └── AbstractWarPackagingTask.java
│ ├── WarExplodedMojo.java
│ ├── util
│ ├── DependencyInfo.java
│ ├── WebappStructureSerializer.java
│ ├── ClassesPackager.java
│ ├── WarUtils.java
│ ├── PathSet.java
│ └── WebappStructure.java
│ ├── WarManifestMojo.java
│ ├── Overlay.java
│ └── SeimiMojo.java
├── readme.md
├── pom.xml
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/*
2 | .idea
3 | *.iml
4 | target
5 | target/*
6 | *.class
7 | .classpath
8 | .project
9 | .settings/
--------------------------------------------------------------------------------
/src/main/resources/template/seimi.cfg:
--------------------------------------------------------------------------------
1 | [init_cfg]
2 | params=-c basic -p 8080
3 |
4 | [linux]
5 | stdout=/tmp/seimicrawler.stdout.log
--------------------------------------------------------------------------------
/src/main/resources/template/run.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set JAVA_CMD=java
3 | set SEIMI_HOME=%cd%
4 | set CLASS_PATH=.;%SEIMI_HOME%\seimi\classes;%SEIMI_HOME%\seimi\lib\*;
5 | % windows环境下注意日志输出编码要与系统控制台一致 %
6 | set SEIMI_SYS_ARGS=-Dfile.encoding=GBK
7 | % e.g. -c 这里指定要启动的Crawler的name,-p 参数为数字,是启动该端口号的内置http服务接受http接口发送过来的Request %
8 | %JAVA_CMD% -cp %CLASS_PATH% %SEIMI_SYS_ARGS% cn.wanghaomiao.seimi.boot.Run -p %1 -c %2
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/TemplateTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi;
2 |
3 |
4 | import org.apache.commons.io.FileUtils;
5 | import org.apache.commons.io.IOUtils;
6 | import org.apache.maven.plugin.logging.Log;
7 |
8 | import java.io.File;
9 | import java.net.URL;
10 |
11 | /**
12 | * @author github.com/zhegexiaohuozi [seimimaster@gmail.com]
13 | * @since 2015/12/28.
14 | */
15 | public class TemplateTask {
16 | private File outDir;
17 | private Log log;
18 |
19 | public TemplateTask(File outDir, Log log) {
20 | this.outDir = outDir;
21 | this.log = log;
22 | }
23 |
24 | public void createBinFile() {
25 | try {
26 | File bin = new File(outDir, "bin");
27 | bin.mkdir();
28 | createFile(bin, "seimi.cfg");
29 | createFile(bin, "run.bat");
30 | createFile(bin, "run.sh");
31 |
32 | } catch (Exception e) {
33 | log.error(e.getMessage(), e);
34 | }
35 | }
36 |
37 | public void createFile(File dir, String fileName) {
38 | try {
39 | URL resource = this.getClass().getClassLoader().getResource("template/" + fileName);
40 | assert resource != null;
41 | String content = IOUtils.toString(resource.openStream());
42 | content = content.replaceAll("\r","");
43 | FileUtils.writeStringToFile(new File(dir, fileName),content);
44 | } catch (Exception e) {
45 | log.error(e.getMessage(), e);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/WarInPlaceMojo.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.plugin.MojoExecutionException;
23 | import org.apache.maven.plugin.MojoFailureException;
24 | import org.apache.maven.plugins.annotations.Mojo;
25 | import org.apache.maven.plugins.annotations.ResolutionScope;
26 |
27 | /**
28 | * Generate the webapp in the WAR source directory.
29 | *
30 | * @version $Id: WarInPlaceMojo.java 1637197 2014-11-06 19:46:57Z khmarbaise $
31 | */
32 | @Mojo( name = "inplace", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true )
33 | public class WarInPlaceMojo
34 | extends AbstractWarMojo
35 | {
36 | /**
37 | * {@inheritDoc}
38 | */
39 | public void execute()
40 | throws MojoExecutionException, MojoFailureException
41 | {
42 | getLog().info( "Generating webapp in source directory [" + getWarSourceDirectory() + "]" );
43 |
44 | buildExplodedWebapp( getWarSourceDirectory() );
45 | }
46 | }
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/overlay/InvalidOverlayConfigurationException.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.overlay;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.plugin.MojoExecutionException;
23 |
24 | /**
25 | * Thrown if the overlay configuration is invalid.
26 | *
27 | * @author Stephane Nicoll
28 | * @version $Id: InvalidOverlayConfigurationException.java 1637197 2014-11-06 19:46:57Z khmarbaise $
29 | */
30 | public class InvalidOverlayConfigurationException
31 | extends MojoExecutionException
32 | {
33 |
34 | /**
35 | * @param string Set the message of the exception.
36 | */
37 | public InvalidOverlayConfigurationException( String string )
38 | {
39 | super( string );
40 | }
41 |
42 | /**
43 | * @param string Set the message of the exception.
44 | * @param throwable {@link Throwable}
45 | */
46 | public InvalidOverlayConfigurationException( String string, Throwable throwable )
47 | {
48 | super( string, throwable );
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/WarPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.plugin.MojoExecutionException;
23 | import org.apache.maven.plugin.MojoFailureException;
24 |
25 | /**
26 | * The base packaging task.
27 | *
28 | * @author Stephane Nicoll
29 | * @version $Id: WarPackagingTask.java 1628849 2014-10-01 22:03:26Z khmarbaise $
30 | */
31 | public interface WarPackagingTask
32 | {
33 |
34 | /**
35 | * Performs the packaging for the specified task.
36 | *
37 | * The task is responsible to update the packaging context, namely with the files that have been copied.
38 | *
39 | * @param context the packaging context
40 | * @throws MojoExecutionException if an error occurred
41 | * @throws MojoFailureException if the project configuration is invalid
42 | */
43 | void performPackaging( WarPackagingContext context )
44 | throws MojoExecutionException, MojoFailureException;
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/WarPostPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.plugin.MojoExecutionException;
23 | import org.apache.maven.plugin.MojoFailureException;
24 |
25 | /**
26 | * Defines tasks that should be performed after the packaging.
27 | *
28 | * @author Stephane Nicoll
29 | * @version $Id: WarPostPackagingTask.java 1628849 2014-10-01 22:03:26Z khmarbaise $
30 | */
31 | public interface WarPostPackagingTask
32 | {
33 |
34 | /**
35 | * Executes the post packaging task.
36 | *
37 | * The packaging context hold all information regarding the webapp that has been packaged.
38 | *
39 | * @param context the packaging context
40 | * @throws MojoExecutionException if an error occurred
41 | * @throws MojoFailureException if a failure occurred
42 | */
43 | void performPostPackaging( WarPackagingContext context )
44 | throws MojoExecutionException, MojoFailureException;
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/WarExplodedMojo.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.plugin.MojoExecutionException;
23 | import org.apache.maven.plugin.MojoFailureException;
24 | import org.apache.maven.plugins.annotations.LifecyclePhase;
25 | import org.apache.maven.plugins.annotations.Mojo;
26 | import org.apache.maven.plugins.annotations.ResolutionScope;
27 |
28 | /**
29 | * Create an exploded webapp in a specified directory.
30 | *
31 | * @version $Id: WarExplodedMojo.java 1637197 2014-11-06 19:46:57Z khmarbaise $
32 | */
33 | // CHECKSTYLE_OFF: LineLength
34 | @Mojo( name = "exploded", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, requiresDependencyResolution = ResolutionScope.RUNTIME )
35 | public class WarExplodedMojo
36 | extends AbstractWarMojo
37 | {
38 | /**
39 | * {@inheritDoc}
40 | */
41 | public void execute()
42 | throws MojoExecutionException, MojoFailureException
43 | {
44 | getLog().info( "Exploding webapp" );
45 |
46 | buildExplodedWebapp( getWebappDirectory() );
47 | }
48 |
49 | }
50 | // CHECKSTYLE_ON: LineLength
51 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/overlay/DefaultOverlay.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.overlay;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.artifact.Artifact;
23 | import cn.wanghaomiao.maven.plugin.seimi.Overlay;
24 |
25 | /**
26 | * A default overlay implementation based on an {@link Artifact}.
27 | *
28 | * @author Stephane Nicoll
29 | * @version $Id: DefaultOverlay.java 1628849 2014-10-01 22:03:26Z khmarbaise $
30 | */
31 | public class DefaultOverlay
32 | extends Overlay
33 | {
34 |
35 | /**
36 | * Creates an overlay for the specified artifact.
37 | *
38 | * @param a the artifact
39 | */
40 | public DefaultOverlay( Artifact a )
41 | {
42 | super();
43 | setGroupId( a.getGroupId() );
44 | setArtifactId( a.getArtifactId() );
45 | setClassifier( a.getClassifier() );
46 | setArtifact( a );
47 | setType( a.getType() );
48 | }
49 |
50 | /**
51 | * Creates an overlay for the specified artifact.
52 | *
53 | * @param a the artifact
54 | * @param includes the includes to use
55 | * @param excludes the excludes to use
56 | */
57 | public DefaultOverlay( Artifact a, String includes, String excludes )
58 | {
59 | this( a );
60 | setIncludes( includes );
61 | setExcludes( excludes );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/CopyUserManifestTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 |
25 | import org.apache.maven.plugin.MojoExecutionException;
26 | import org.apache.maven.plugin.MojoFailureException;
27 | import org.apache.maven.plugin.logging.Log;
28 | import org.apache.maven.plugin.logging.SystemStreamLog;
29 |
30 | /**
31 | * @author Haikal Saadh
32 | *
33 | */
34 | public class CopyUserManifestTask
35 | extends AbstractWarPackagingTask
36 | {
37 |
38 | /** Instance logger */
39 | private Log log;
40 |
41 | public Log getLog()
42 | {
43 | if ( log == null )
44 | {
45 | log = new SystemStreamLog();
46 | }
47 | return log;
48 | }
49 |
50 | public void setLog( Log log )
51 | {
52 | this.log = log;
53 | }
54 |
55 | public void performPackaging( WarPackagingContext context )
56 | throws MojoExecutionException, MojoFailureException
57 | {
58 | File userManifest = context.getArchive().getManifestFile();
59 | if ( userManifest != null )
60 | {
61 |
62 | try
63 | {
64 | getLog().info( "Copying manifest..." );
65 | File metainfDir = new File( context.getWebappDirectory(), META_INF_PATH );
66 | copyFile( context, userManifest, new File( metainfDir, "MANIFEST.MF" ), "META-INF/MANIFEST.MF", true );
67 |
68 | }
69 | catch ( IOException e )
70 | {
71 | throw new MojoExecutionException( "Error copying user manifest", e );
72 | }
73 | }
74 |
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | maven-seimicrawler-plugin
2 | ==========
3 | Package seimicrawler project so that can be fast and standalone deployed.It is based on maven-war-plugin and modified.
4 |
5 | `maven-seimicrawler-plugin`是基于`maven-war-plugin` v2.6版本修改定制而来。旨在方便开发者对于SeimiCrawler工程的快速打包并独立部署。
6 |
7 | # 开始 #
8 | pom添加添加plugin
9 | ```
10 |
11 | cn.wanghaomiao
12 | maven-seimicrawler-plugin
13 | 1.3.0
14 |
15 |
16 | package
17 |
18 | build
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | ```
28 | 执行`mvn clean package`即可,包目录结构如下:
29 | ```
30 | .
31 | ├── bin # 相应的脚本中也有具体启动参数说明介绍,在此不再敖述
32 | │ ├── run.bat # windows下启动脚本
33 | │ └── run.sh # Linux下启动脚本
34 | │ └── seimi.cfg # Linux下启动配置
35 | └── seimi
36 | ├── classes # Crawler工程业务类及相关配置文件目录
37 | └── lib # 工程依赖包目录
38 | ```
39 |
40 | ## 启动说明 ##
41 |
42 | ### Linux ###
43 |
44 | #### 启动说明 ####
45 | ```
46 | SeimiCrawler service helper
47 | usage: run.sh [options]
48 | start start service
49 | stop stop service
50 | help Print service help
51 | ```
52 |
53 | - `./bin/run.sh start`
54 | 启动seimicrawler服务
55 |
56 | - `./bin/run.sh stop`
57 | 停止当前seimicrawler服务
58 |
59 | - `./bin/run.sh help`
60 | 查看使用说明
61 |
62 | #### 配置文件 ####
63 |
64 | ```
65 | [init_cfg]
66 | params=-c basic -p 8080
67 |
68 | [linux]
69 | stdout=/tmp/seimicrawler.stdout.log
70 | ```
71 | `params`只启动seimicrawler时启动参数,其中`-p`指定端口启动一个内嵌的http服务,接受通过http接口(参考SeimiCrawler文档有说明具体的接口)添加抓取请求或是查询抓取状态等操作,`-c`指定要启动的crawler的名称,如果不指定,默认是以workers形式启动所有扫描到的crawler,并开始监听抓取请求。两个参数都不是必须的。`stdout`配置的是seimicrawler服务启动后控制台日志输出路径。
72 |
73 | ### windows ###
74 |
75 | windows脚本比较简单,全部内容都在`run.bat`里了,直接在里面改就好了。
76 |
77 | # SeimiCrawler项目 #
78 | SeimiCrawler是一个敏捷的,独立部署的,支持分布式的Java爬虫框架,希望能在最大程度上降低新手开发一个可用性高且性能不差的爬虫系统的门槛,以及提升开发爬虫系统的开发效率。在SeimiCrawler的世界里,绝大多数人只需关心去写抓取的业务逻辑就够了,其余的Seimi帮你搞定。设计思想上SeimiCrawler受Python的爬虫框架Scrapy启发很大,同时融合了Java语言本身特点与Spring的特性,并希望在国内更方便且普遍的使用更有效率的XPath解析HTML,所以SeimiCrawler默认的HTML解析器是[JsoupXpath](http://jsoupxpath.wanghaomiao.cn)(独立扩展项目,非jsoup自带),默认解析提取HTML数据工作均使用XPath来完成(当然,数据处理亦可以自行选择其他解析器)。
79 |
80 | > 直达[SeimiCrawler](https://github.com/zhegexiaohuozi/SeimiCrawler)项目
81 |
82 | # 社区讨论 #
83 | 大家有什么问题或建议现在都可以选择通过下面的邮件列表讨论,首次发言前需先订阅并等待审核通过(主要用来屏蔽广告宣传等)
84 | - 订阅:请发邮件到 `seimicrawler+subscribe@googlegroups.com`
85 | - 发言:请发邮件到 `seimicrawler@googlegroups.com`
86 | - 退订:请发邮件至 `seimicrawler+unsubscribe@googlegroups.com`
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/SaveWebappStructurePostPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import cn.wanghaomiao.maven.plugin.seimi.util.WebappStructureSerializer;
23 | import org.apache.maven.plugin.MojoExecutionException;
24 | import org.apache.maven.plugin.MojoFailureException;
25 |
26 | import java.io.File;
27 | import java.io.IOException;
28 |
29 | /**
30 | * Saves the webapp structure cache.
31 | *
32 | * @author Stephane Nicoll
33 | * @version $Id: SaveWebappStructurePostPackagingTask.java 1637197 2014-11-06 19:46:57Z khmarbaise $
34 | */
35 | public class SaveWebappStructurePostPackagingTask
36 | implements WarPostPackagingTask
37 | {
38 |
39 | private final File targetFile;
40 |
41 | private final WebappStructureSerializer serialier;
42 |
43 | /**
44 | * @param targetFile {@link #targetFile}
45 | */
46 | public SaveWebappStructurePostPackagingTask( File targetFile )
47 | {
48 | this.targetFile = targetFile;
49 | this.serialier = new WebappStructureSerializer();
50 | }
51 |
52 | /**
53 | * {@inheritDoc}
54 | */
55 | public void performPostPackaging( WarPackagingContext context )
56 | throws MojoExecutionException, MojoFailureException
57 | {
58 | if ( targetFile == null )
59 | {
60 | context.getLog().debug( "Cache usage is disabled, not saving webapp structure." );
61 | }
62 | else
63 | {
64 | try
65 | {
66 | serialier.toXml( context.getWebappStructure(), targetFile );
67 | context.getLog().debug( "Cache saved successfully." );
68 | }
69 | catch ( IOException e )
70 | {
71 | throw new MojoExecutionException( "Could not save webapp structure", e );
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/util/DependencyInfo.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.util;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.model.Dependency;
23 |
24 | /**
25 | * Holds a dependency and packaging information.
26 | *
27 | * @author Stephane Nicoll
28 | * @version $Id: DependencyInfo.java 1637197 2014-11-06 19:46:57Z khmarbaise $
29 | */
30 | public class DependencyInfo
31 | {
32 |
33 | private final Dependency dependency;
34 |
35 | private String targetFileName;
36 |
37 | /**
38 | * Creates a new instance.
39 | *
40 | * @param dependency the dependency
41 | */
42 | public DependencyInfo( Dependency dependency )
43 | {
44 | this.dependency = dependency;
45 | }
46 |
47 | /**
48 | * Returns the dependency.
49 | *
50 | * @return the dependency
51 | */
52 | public Dependency getDependency()
53 | {
54 | return dependency;
55 | }
56 |
57 | /**
58 | * Returns the target filen ame of the dependency. If no target file name is associated, returns null.
59 | *
60 | * @return the target file name or null
61 | */
62 | public String getTargetFileName()
63 | {
64 | return targetFileName;
65 | }
66 |
67 | /**
68 | * Sets the target file name.
69 | *
70 | * @param targetFileName the target file name
71 | */
72 | public void setTargetFileName( String targetFileName )
73 | {
74 | this.targetFileName = targetFileName;
75 | }
76 |
77 | /**
78 | * {@inheritDoc}
79 | */
80 | public boolean equals( Object o )
81 | {
82 | if ( this == o )
83 | {
84 | return true;
85 | }
86 | if ( o == null || getClass() != o.getClass() )
87 | {
88 | return false;
89 | }
90 |
91 | DependencyInfo that = (DependencyInfo) o;
92 |
93 | if ( dependency != null ? !dependency.equals( that.dependency ) : that.dependency != null )
94 | {
95 | return false;
96 | }
97 |
98 | return true;
99 | }
100 |
101 | /**
102 | * {@inheritDoc}
103 | */
104 | public int hashCode()
105 | {
106 | int result;
107 | result = ( dependency != null ? dependency.hashCode() : 0 );
108 | result = 31 * result + ( targetFileName != null ? targetFileName.hashCode() : 0 );
109 | return result;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/WarManifestMojo.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.archiver.MavenArchiver;
23 | import org.apache.maven.artifact.DependencyResolutionRequiredException;
24 | import org.apache.maven.plugin.MojoExecutionException;
25 | import org.apache.maven.plugins.annotations.Component;
26 | import org.apache.maven.plugins.annotations.LifecyclePhase;
27 | import org.apache.maven.plugins.annotations.Mojo;
28 | import org.apache.maven.plugins.annotations.ResolutionScope;
29 | import org.codehaus.plexus.archiver.Archiver;
30 | import org.codehaus.plexus.archiver.jar.Manifest;
31 | import org.codehaus.plexus.archiver.jar.ManifestException;
32 | import org.codehaus.plexus.archiver.war.WarArchiver;
33 | import org.codehaus.plexus.util.IOUtil;
34 | import org.codehaus.plexus.util.WriterFactory;
35 |
36 | import java.io.File;
37 | import java.io.IOException;
38 | import java.io.PrintWriter;
39 |
40 | /**
41 | * Generate a manifest for this webapp. The manifest file is created in the warSourceDirectory.
42 | *
43 | * @author Mike Perham
44 | * @version $Id: WarManifestMojo.java 1636820 2014-11-05 08:27:25Z khmarbaise $
45 | */
46 | // CHECKSTYLE_OFF: LineLength
47 | @Mojo( name = "manifest", defaultPhase = LifecyclePhase.PROCESS_RESOURCES, threadSafe = true, requiresDependencyResolution = ResolutionScope.RUNTIME )
48 | // CHECKSTYLE_ON: LineLength
49 | public class WarManifestMojo
50 | extends AbstractWarMojo
51 | {
52 | /**
53 | * The WAR archiver.
54 | */
55 | @Component( role = Archiver.class, hint = "war" )
56 | private WarArchiver warArchiver;
57 |
58 | /**
59 | * Executes this mojo on the current project.
60 | *
61 | * @throws MojoExecutionException if an error occurred while building the webapp
62 | */
63 | public void execute()
64 | throws MojoExecutionException
65 | {
66 | File manifestDir = new File( getWarSourceDirectory(), "META-INF" );
67 | if ( !manifestDir.exists() )
68 | {
69 | manifestDir.mkdirs();
70 | }
71 | File manifestFile = new File( manifestDir, "MANIFEST.MF" );
72 | MavenArchiver ma = new MavenArchiver();
73 | ma.setArchiver( warArchiver );
74 | ma.setOutputFile( manifestFile );
75 |
76 | PrintWriter printWriter = null;
77 | try
78 | {
79 | Manifest mf = ma.getManifest( getSession(), getProject(), getArchive() );
80 | printWriter = new PrintWriter( WriterFactory.newWriter( manifestFile, WriterFactory.UTF_8 ) );
81 | mf.write( printWriter );
82 | }
83 | catch ( ManifestException e )
84 | {
85 | throw new MojoExecutionException( "Error preparing the manifest: " + e.getMessage(), e );
86 | }
87 | catch ( DependencyResolutionRequiredException e )
88 | {
89 | throw new MojoExecutionException( "Error preparing the manifest: " + e.getMessage(), e );
90 | }
91 | catch ( IOException e )
92 | {
93 | throw new MojoExecutionException( "Error preparing the manifest: " + e.getMessage(), e );
94 | }
95 | finally
96 | {
97 | IOUtil.close( printWriter );
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/util/WebappStructureSerializer.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.util;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import com.thoughtworks.xstream.XStream;
23 | import com.thoughtworks.xstream.io.xml.DomDriver;
24 | import org.apache.maven.model.Dependency;
25 | import org.codehaus.plexus.util.IOUtil;
26 | import org.codehaus.plexus.util.ReaderFactory;
27 | import org.codehaus.plexus.util.WriterFactory;
28 |
29 | import java.io.File;
30 | import java.io.IOException;
31 | import java.io.Reader;
32 | import java.io.Writer;
33 |
34 | /**
35 | * Serializes {@link WebappStructure} back and forth.
36 | *
37 | * @author Stephane Nicoll
38 | * @version $Id: WebappStructureSerializer.java 1636820 2014-11-05 08:27:25Z khmarbaise $
39 | */
40 | public class WebappStructureSerializer
41 | {
42 |
43 | private static final XStream XSTREAM;
44 |
45 | static
46 | {
47 | XSTREAM = new XStream( new DomDriver() );
48 |
49 | // Register aliases
50 | XSTREAM.alias( "webapp-structure", WebappStructure.class );
51 | XSTREAM.alias( "path-set", PathSet.class );
52 | XSTREAM.alias( "dependency", Dependency.class );
53 |
54 | }
55 |
56 | /**
57 | * Creates a new instance of the serializer.
58 | */
59 | public WebappStructureSerializer()
60 | {
61 | }
62 |
63 | /**
64 | * Reads the {@link WebappStructure} from the specified file.
65 | *
66 | * @param file the file containing the webapp structure
67 | * @return the webapp structure
68 | * @throws IOException if an error occurred while reading the structure
69 | */
70 | public WebappStructure fromXml( File file )
71 | throws IOException
72 | {
73 | Reader reader = null;
74 |
75 | try
76 | {
77 | reader = ReaderFactory.newXmlReader( file );
78 | return (WebappStructure) XSTREAM.fromXML( reader );
79 | }
80 | finally
81 | {
82 | IOUtil.close( reader );
83 | }
84 | }
85 |
86 | /**
87 | * Saves the {@link WebappStructure} to the specified file.
88 | *
89 | * @param webappStructure the structure to save
90 | * @param targetFile the file to use to save the structure
91 | * @throws IOException if an error occurred while saving the webapp structure
92 | */
93 | public void toXml( WebappStructure webappStructure, File targetFile )
94 | throws IOException
95 | {
96 | // CHECKSTYLE_OFF: LineLength
97 | Writer writer = null;
98 | try
99 | {
100 | if ( !targetFile.getParentFile().exists() && !targetFile.getParentFile().mkdirs() )
101 | {
102 | throw new IOException( "Could not create parent [" + targetFile.getParentFile().getAbsolutePath() + "]" );
103 | }
104 |
105 | if ( !targetFile.exists() && !targetFile.createNewFile() )
106 | {
107 | throw new IOException( "Could not create file [" + targetFile.getAbsolutePath() + "]" );
108 | }
109 | writer = WriterFactory.newXmlWriter( targetFile );
110 | XSTREAM.toXML( webappStructure, writer );
111 | }
112 | finally
113 | {
114 | IOUtil.close( writer );
115 | }
116 | // CHECKSTYLE_ON: LineLength
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/util/ClassesPackager.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.util;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import cn.wanghaomiao.maven.plugin.seimi.packaging.AbstractWarPackagingTask;
23 | import org.apache.maven.archiver.MavenArchiveConfiguration;
24 | import org.apache.maven.archiver.MavenArchiver;
25 | import org.apache.maven.artifact.DependencyResolutionRequiredException;
26 | import org.apache.maven.execution.MavenSession;
27 | import org.apache.maven.plugin.MojoExecutionException;
28 | import org.apache.maven.project.MavenProject;
29 | import org.codehaus.plexus.archiver.ArchiverException;
30 | import org.codehaus.plexus.archiver.jar.JarArchiver;
31 | import org.codehaus.plexus.archiver.jar.ManifestException;
32 |
33 | import java.io.File;
34 | import java.io.IOException;
35 |
36 | /**
37 | * Packages the content of the classes directory.
38 | *
39 | * @author Stephane Nicoll
40 | * @version $Id: ClassesPackager.java 1628849 2014-10-01 22:03:26Z khmarbaise $
41 | */
42 | public class ClassesPackager
43 | {
44 |
45 | /**
46 | * Creates a new instance.
47 | */
48 | public ClassesPackager()
49 | {
50 | super();
51 | }
52 |
53 | /**
54 | * Package the classes
55 | *
56 | * @param classesDirectory the classes directory
57 | * @param targetFile the target file
58 | * @param jarArchiver the jar archiver to use
59 | * @param session the current session
60 | * @param project the related project
61 | * @param archiveConfiguration the archive configuration to use
62 | * @throws MojoExecutionException if an error occurred while creating the archive
63 | */
64 | public void packageClasses( File classesDirectory, File targetFile, JarArchiver jarArchiver, MavenSession session,
65 | MavenProject project, MavenArchiveConfiguration archiveConfiguration )
66 | throws MojoExecutionException
67 | {
68 |
69 | try
70 | {
71 | final MavenArchiver archiver = new MavenArchiver();
72 | archiver.setArchiver( jarArchiver );
73 | archiver.setOutputFile( targetFile );
74 | archiver.getArchiver().addDirectory( classesDirectory );
75 | archiver.createArchive( session, project, archiveConfiguration );
76 | }
77 | catch ( ArchiverException e )
78 | {
79 | throw new MojoExecutionException( "Could not create classes archive", e );
80 | }
81 | catch ( ManifestException e )
82 | {
83 | throw new MojoExecutionException( "Could not create classes archive", e );
84 | }
85 | catch ( IOException e )
86 | {
87 | throw new MojoExecutionException( "Could not create classes archive", e );
88 | }
89 | catch ( DependencyResolutionRequiredException e )
90 | {
91 | throw new MojoExecutionException( "Could not create classes archive", e );
92 | }
93 | }
94 |
95 | /**
96 | * Returns the classes directory from the specified webapp directory.
97 | *
98 | * @param webappDirectory the webapp directory
99 | * @return the classes directory of the specified webapp directory
100 | */
101 | public File getClassesDirectory( File webappDirectory )
102 | {
103 | return new File( webappDirectory, AbstractWarPackagingTask.CLASSES_PATH );
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/ClassesPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.artifact.Artifact;
23 | import org.apache.maven.artifact.factory.ArtifactFactory;
24 | import org.apache.maven.plugin.MojoExecutionException;
25 | import cn.wanghaomiao.maven.plugin.seimi.Overlay;
26 | import cn.wanghaomiao.maven.plugin.seimi.util.ClassesPackager;
27 | import cn.wanghaomiao.maven.plugin.seimi.util.PathSet;
28 | import org.apache.maven.project.MavenProject;
29 | import org.codehaus.plexus.interpolation.InterpolationException;
30 |
31 | import java.io.File;
32 | import java.io.IOException;
33 |
34 | /**
35 | * Handles the classes directory that needs to be packaged in the web application.
36 | *
37 | * Based on the {@link WarPackagingContext#archiveClasses()} flag the resources either copied into to
38 | * WEB-INF/classes directory or archived in a jar within the WEB-INF/lib directory.
39 | *
40 | * @author Stephane Nicoll
41 | * @version $Id: ClassesPackagingTask.java 1637197 2014-11-06 19:46:57Z khmarbaise $
42 | */
43 | public class ClassesPackagingTask
44 | extends AbstractWarPackagingTask
45 | {
46 | private final Overlay currentProjectOverlay;
47 |
48 | /**
49 | * @param currentProjectOverlay {@link #currentProjectOverlay}
50 | */
51 | public ClassesPackagingTask( Overlay currentProjectOverlay )
52 | {
53 | this.currentProjectOverlay = currentProjectOverlay;
54 | }
55 |
56 | /**
57 | * {@inheritDoc}
58 | */
59 | public void performPackaging( WarPackagingContext context )
60 | throws MojoExecutionException
61 | {
62 | final File webappClassesDirectory = new File( context.getWebappDirectory(), CLASSES_PATH );
63 | if ( !webappClassesDirectory.exists() )
64 | {
65 | webappClassesDirectory.mkdirs();
66 | }
67 |
68 | if ( context.getClassesDirectory().exists() && !context.getClassesDirectory().equals( webappClassesDirectory ) )
69 | {
70 | if ( context.archiveClasses() )
71 | {
72 | generateJarArchive( context );
73 | }
74 | else
75 | {
76 | final PathSet sources = getFilesToIncludes( context.getClassesDirectory(), null, null );
77 | try
78 | {
79 | copyFiles( currentProjectOverlay.getId(), context, context.getClassesDirectory(), sources,
80 | CLASSES_PATH, false );
81 | }
82 | catch ( IOException e )
83 | {
84 | throw new MojoExecutionException( "Could not copy webapp classes ["
85 | + context.getClassesDirectory().getAbsolutePath() + "]", e );
86 | }
87 | }
88 | }
89 | }
90 |
91 | /**
92 | * @param context The warPackingContext.
93 | * @throws MojoExecutionException In casae of an error.
94 | */
95 | protected void generateJarArchive( WarPackagingContext context )
96 | throws MojoExecutionException
97 | {
98 | MavenProject project = context.getProject();
99 | ArtifactFactory factory = context.getArtifactFactory();
100 | Artifact artifact =
101 | factory.createBuildArtifact( project.getGroupId(), project.getArtifactId(), project.getVersion(), "jar" );
102 | String archiveName;
103 | try
104 | {
105 | archiveName = getArtifactFinalName( context, artifact );
106 | }
107 | catch ( InterpolationException e )
108 | {
109 | throw new MojoExecutionException( "Could not get the final name of the artifact [" + artifact.getGroupId()
110 | + ":" + artifact.getArtifactId() + ":" + artifact.getVersion() + "]", e );
111 | }
112 | final String targetFilename = LIB_PATH + archiveName;
113 |
114 | if ( context.getWebappStructure().registerFile( currentProjectOverlay.getId(), targetFilename ) )
115 | {
116 | final File libDirectory = new File( context.getWebappDirectory(), LIB_PATH );
117 | final File jarFile = new File( libDirectory, archiveName );
118 | final ClassesPackager packager = new ClassesPackager();
119 | packager.packageClasses( context.getClassesDirectory(), jarFile, context.getJarArchiver(),
120 | context.getSession(), project, context.getArchive() );
121 | }
122 | else
123 | {
124 | context.getLog().warn( "Could not generate archive classes file [" + targetFilename
125 | + "] has already been copied." );
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | 4.0.0
9 |
10 |
11 | org.sonatype.oss
12 | oss-parent
13 | 7
14 |
15 | cn.wanghaomiao
16 | maven-seimicrawler-plugin
17 | 1.3.0
18 | maven-plugin
19 |
20 | SeimiCrawler Package Plugin
21 |
22 | Package seimicrawler project so that can be fast and standalone deployed.It is based on maven-war-plugin and modified.
23 | 这是专为SeimiCrawler工程专门定制的一个maven发布工具,意在简化开发者项目发布与部署流程。本插件是基于Apache的maven-war-plugin修改而来,依然采用Apache License Version2.0发布。
24 |
25 |
26 |
27 | 2.6
28 | 1.3
29 | 2.2.1
30 |
31 |
32 |
33 |
34 | Auke Schrijnen
35 |
36 |
37 | Ludwig Magnusson
38 |
39 |
40 | Hayarobi Park
41 |
42 |
43 | Haomiao Wang
44 |
45 |
46 |
47 |
48 |
49 | org.apache.maven
50 | maven-plugin-api
51 | ${mavenVersion}
52 |
53 |
54 | org.apache.maven
55 | maven-artifact
56 | ${mavenVersion}
57 |
58 |
59 | org.apache.maven
60 | maven-model
61 | ${mavenVersion}
62 |
63 |
64 | org.apache.maven
65 | maven-project
66 | ${mavenVersion}
67 |
68 |
69 | org.apache.maven
70 | maven-core
71 | ${mavenVersion}
72 |
73 |
74 | org.apache.maven
75 | maven-settings
76 | ${mavenVersion}
77 |
78 |
79 | org.apache.maven
80 | maven-archiver
81 | ${mavenArchiverVersion}
82 |
83 |
84 | org.apache.maven.plugin-tools
85 | maven-plugin-annotations
86 | 3.4
87 | provided
88 |
89 |
90 | org.codehaus.plexus
91 | plexus-io
92 | 2.4.1
93 |
94 |
95 | commons-io
96 | commons-io
97 | 2.2
98 |
99 |
100 | org.codehaus.plexus
101 | plexus-archiver
102 | 2.9
103 |
104 |
105 | org.codehaus.plexus
106 | plexus-interpolation
107 | 1.21
108 |
109 |
110 |
111 | com.thoughtworks.xstream
112 | xstream
113 | 1.4.4
114 |
115 |
116 |
117 | org.codehaus.plexus
118 | plexus-utils
119 | 3.0.20
120 |
121 |
122 |
123 | org.apache.maven.shared
124 | maven-filtering
125 | ${mavenFilteringVersion}
126 |
127 |
128 |
129 | org.apache.maven.shared
130 | maven-mapping
131 | 1.0
132 |
133 |
134 | org.freemarker
135 | freemarker
136 | 2.3.23
137 |
138 |
139 |
140 | junit
141 | junit
142 | 4.11
143 | test
144 |
145 |
146 | org.apache.maven.plugin-testing
147 | maven-plugin-testing-harness
148 | 1.3
149 | test
150 |
151 |
152 |
153 |
154 |
155 | org.apache.maven.plugins
156 | maven-plugin-plugin
157 | 3.2
158 |
159 | true
160 |
161 |
162 |
163 | mojo-descriptor
164 |
165 | descriptor
166 |
167 |
168 |
169 | help-goal
170 |
171 | helpmojo
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/util/WarUtils.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.util;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.artifact.Artifact;
23 | import org.apache.maven.model.Dependency;
24 | import org.apache.maven.project.MavenProject;
25 | import org.codehaus.plexus.util.StringUtils;
26 |
27 | /**
28 | * @author Stephane Nicoll
29 | * @version $Id: WarUtils.java 1637197 2014-11-06 19:46:57Z khmarbaise $
30 | */
31 | public class WarUtils
32 | {
33 |
34 | /**
35 | * @param project {@link MavenProject}
36 | * @param dependency {@link Dependency}
37 | * @return {@link Artifact}
38 | */
39 | public static Artifact getArtifact( MavenProject project, Dependency dependency )
40 | {
41 | for ( Object o : project.getArtifacts() )
42 | {
43 | Artifact artifact = (Artifact) o;
44 | if ( artifact.getGroupId().equals( dependency.getGroupId() )
45 | && artifact.getArtifactId().equals( dependency.getArtifactId() )
46 | && artifact.getType().equals( dependency.getType() ) )
47 | {
48 | if ( artifact.getClassifier() == null && dependency.getClassifier() == null )
49 | {
50 | return artifact;
51 | }
52 | else if ( dependency.getClassifier() != null
53 | && dependency.getClassifier().equals( artifact.getClassifier() ) )
54 | {
55 | return artifact;
56 | }
57 | }
58 | }
59 | return null;
60 | }
61 |
62 | /**
63 | * @param artifact {@link Artifact}
64 | * @param dependency {@link Dependency}
65 | * @return is related or not.
66 | */
67 | public static boolean isRelated( Artifact artifact, Dependency dependency )
68 | {
69 | if ( artifact == null || dependency == null )
70 | {
71 | return false;
72 | }
73 |
74 | if ( !StringUtils.equals( artifact.getGroupId(), dependency.getGroupId() ) )
75 | {
76 | return false;
77 | }
78 | if ( !StringUtils.equals( artifact.getArtifactId(), dependency.getArtifactId() ) )
79 | {
80 | return false;
81 | }
82 | if ( artifact.getVersion() != null ? !artifact.getVersion().equals( dependency.getVersion() )
83 | : dependency.getVersion() != null )
84 | {
85 | return false;
86 | }
87 | if ( artifact.getType() != null ? !artifact.getType().equals( dependency.getType() )
88 | : dependency.getType() != null )
89 | {
90 | return false;
91 | }
92 | if ( artifact.getClassifier() != null ? !artifact.getClassifier().equals( dependency.getClassifier() )
93 | : dependency.getClassifier() != null )
94 | {
95 | return false;
96 | }
97 | if ( artifact.getScope() != null ? !artifact.getScope().equals( dependency.getScope() )
98 | : dependency.getScope() != null )
99 | {
100 | return false;
101 | }
102 | if ( artifact.isOptional() != dependency.isOptional() )
103 | {
104 | return false;
105 | }
106 |
107 | return true;
108 | }
109 |
110 | /**
111 | * @param first {@link Dependency}
112 | * @param second {@link Dependency}
113 | * @return are the dependencies equal.
114 | */
115 | public static boolean dependencyEquals( Dependency first, Dependency second )
116 | {
117 | if ( first == second )
118 | {
119 | return true;
120 | }
121 |
122 | if ( first.isOptional() != second.isOptional() )
123 | {
124 | return false;
125 | }
126 | if ( !StringUtils.equals( first.getArtifactId(), second.getArtifactId() ) )
127 | {
128 | return false;
129 | }
130 | if ( first.getClassifier() != null ? !first.getClassifier().equals( second.getClassifier() )
131 | : second.getClassifier() != null )
132 | {
133 | return false;
134 | }
135 | if ( first.getExclusions() != null ? !first.getExclusions().equals( second.getExclusions() )
136 | : second.getExclusions() != null )
137 | {
138 | return false;
139 | }
140 | if ( !StringUtils.equals( first.getGroupId(), second.getGroupId() ) )
141 | {
142 | return false;
143 | }
144 | if ( first.getScope() != null ? !first.getScope().equals( second.getScope() ) : second.getScope() != null )
145 | {
146 | return false;
147 | }
148 | if ( first.getSystemPath() != null ? !first.getSystemPath().equals( second.getSystemPath() )
149 | : second.getSystemPath() != null )
150 | {
151 | return false;
152 | }
153 | if ( first.getType() != null ? !first.getType().equals( second.getType() ) : second.getType() != null )
154 | {
155 | return false;
156 | }
157 | if ( first.getVersion() != null ? !first.getVersion().equals( second.getVersion() )
158 | : second.getVersion() != null )
159 | {
160 | return false;
161 | }
162 | return true;
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/OverlayPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import cn.wanghaomiao.maven.plugin.seimi.util.PathSet;
23 | import org.apache.maven.plugin.MojoExecutionException;
24 | import cn.wanghaomiao.maven.plugin.seimi.Overlay;
25 | import org.codehaus.plexus.util.FileUtils;
26 |
27 | import java.io.File;
28 | import java.io.IOException;
29 |
30 | /**
31 | * Handles an overlay.
32 | *
33 | * @author Stephane Nicoll
34 | * @version $Id: OverlayPackagingTask.java 1637197 2014-11-06 19:46:57Z khmarbaise $
35 | */
36 | public class OverlayPackagingTask
37 | extends AbstractWarPackagingTask
38 | {
39 | private final Overlay overlay;
40 |
41 | /**
42 | * @param overlay {@link #overlay}
43 | * @param currentProjectOverlay current overlay.
44 | */
45 | public OverlayPackagingTask( Overlay overlay, Overlay currentProjectOverlay )
46 | {
47 | if ( overlay == null )
48 | {
49 | throw new NullPointerException( "overlay could not be null." );
50 | }
51 | if ( overlay.equals( currentProjectOverlay ) )
52 | {
53 | throw new IllegalStateException( "Could not handle the current project with this task." );
54 | }
55 | this.overlay = overlay;
56 | }
57 |
58 | /**
59 | * {@inheritDoc}
60 | */
61 | public void performPackaging( WarPackagingContext context )
62 | throws MojoExecutionException
63 | {
64 | context.getLog().debug( "OverlayPackagingTask performPackaging overlay.getTargetPath() "
65 | + overlay.getTargetPath() );
66 | if ( overlay.shouldSkip() )
67 | {
68 | context.getLog().info( "Skipping overlay [" + overlay + "]" );
69 | }
70 | else
71 | {
72 | try
73 | {
74 | context.getLog().info( "Processing overlay [" + overlay + "]" );
75 |
76 | // Step1: Extract if necessary
77 | final File tmpDir = unpackOverlay( context, overlay );
78 |
79 | // Step2: setup
80 | final PathSet includes = getFilesToIncludes( tmpDir, overlay.getIncludes(), overlay.getExcludes() );
81 |
82 | // Copy
83 | if ( null == overlay.getTargetPath() )
84 | {
85 | copyFiles( overlay.getId(), context, tmpDir, includes, overlay.isFiltered() );
86 | }
87 | else
88 | {
89 | // overlay.getTargetPath() must ended with /
90 | // if not we add it
91 | String targetPath = overlay.getTargetPath();
92 | if ( !targetPath.endsWith( "/" ) )
93 | {
94 | targetPath = targetPath + "/";
95 | }
96 | copyFiles( overlay.getId(), context, tmpDir, includes, targetPath, overlay.isFiltered() );
97 | }
98 | }
99 | catch ( IOException e )
100 | {
101 | throw new MojoExecutionException( "Failed to copy file for overlay [" + overlay + "]", e );
102 | }
103 | }
104 | }
105 |
106 | /**
107 | * Unpacks the specified overlay.
108 | *
109 | * Makes sure to skip the unpack process if the overlay has already been unpacked.
110 | *
111 | * @param context the packaging context
112 | * @param overlay the overlay
113 | * @return the directory containing the unpacked overlay
114 | * @throws MojoExecutionException if an error occurred while unpacking the overlay
115 | */
116 | protected File unpackOverlay( WarPackagingContext context, Overlay overlay )
117 | throws MojoExecutionException
118 | {
119 | final File tmpDir = getOverlayTempDirectory( context, overlay );
120 |
121 | // TODO: not sure it's good, we should reuse the markers of the dependency plugin
122 | if ( FileUtils.sizeOfDirectory( tmpDir ) == 0
123 | || overlay.getArtifact().getFile().lastModified() > tmpDir.lastModified() )
124 | {
125 | doUnpack( context, overlay.getArtifact().getFile(), tmpDir );
126 | }
127 | else
128 | {
129 | context.getLog().debug( "Overlay [" + overlay + "] was already unpacked" );
130 | }
131 | return tmpDir;
132 | }
133 |
134 | /**
135 | * Returns the directory to use to unpack the specified overlay.
136 | *
137 | * @param context the packaging context
138 | * @param overlay the overlay
139 | * @return the temp directory for the overlay
140 | */
141 | protected File getOverlayTempDirectory( WarPackagingContext context, Overlay overlay )
142 | {
143 | final File groupIdDir = new File( context.getOverlaysWorkDirectory(), overlay.getGroupId() );
144 | if ( !groupIdDir.exists() )
145 | {
146 | groupIdDir.mkdir();
147 | }
148 | String directoryName = overlay.getArtifactId();
149 | if ( overlay.getClassifier() != null )
150 | {
151 | directoryName = directoryName + "-" + overlay.getClassifier();
152 | }
153 | final File result = new File( groupIdDir, directoryName );
154 | if ( !result.exists() )
155 | {
156 | result.mkdirs();
157 | }
158 | return result;
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/WarPackagingContext.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import java.io.File;
23 | import java.util.List;
24 |
25 | import cn.wanghaomiao.maven.plugin.seimi.util.WebappStructure;
26 | import org.apache.maven.archiver.MavenArchiveConfiguration;
27 | import org.apache.maven.artifact.factory.ArtifactFactory;
28 | import org.apache.maven.execution.MavenSession;
29 | import org.apache.maven.plugin.logging.Log;
30 | import org.apache.maven.project.MavenProject;
31 | import org.apache.maven.shared.filtering.MavenFileFilter;
32 | import org.apache.maven.shared.utils.io.FileUtils.FilterWrapper;
33 | import org.codehaus.plexus.archiver.jar.JarArchiver;
34 | import org.codehaus.plexus.archiver.manager.ArchiverManager;
35 |
36 | /**
37 | * The packaging context.
38 | *
39 | * @author Stephane Nicoll
40 | * @version $Id: WarPackagingContext.java 1637197 2014-11-06 19:46:57Z khmarbaise $
41 | */
42 | public interface WarPackagingContext
43 | {
44 | /**
45 | * Returns the maven project.
46 | *
47 | * @return the project
48 | */
49 | MavenProject getProject();
50 |
51 | /**
52 | * Returns the webapp directory. Packaging tasks should use this directory to generate the webapp.
53 | *
54 | * @return the webapp directory
55 | */
56 | File getWebappDirectory();
57 |
58 | /**
59 | * Returns the main webapp source directory.
60 | *
61 | * @return the webapp source directory
62 | */
63 | File getWebappSourceDirectory();
64 |
65 | /**
66 | * Returns the webapp source includes.
67 | *
68 | * @return the webapp source includes
69 | */
70 | String[] getWebappSourceIncludes();
71 |
72 | /**
73 | * Returns {@code true} if empty directories should be includes, othewrwise {@code false}
74 | *
75 | * @return {@code true} if empty directories should be includes, othewrwise {@code false}
76 | */
77 | boolean isWebappSourceIncludeEmptyDirectories();
78 |
79 | /**
80 | * Returns the webapp source excludes.
81 | *
82 | * @return the webapp source excludes
83 | */
84 | String[] getWebappSourceExcludes();
85 |
86 | /**
87 | * Returns the directory holding generated classes.
88 | *
89 | * @return the classes directory
90 | */
91 | File getClassesDirectory();
92 |
93 | /**
94 | * Specify whether the classes resources should be archived in the WEB-INF/lib of the generated web app.
95 | *
96 | * @return true if the classes should be archived, false otherwise
97 | */
98 | boolean archiveClasses();
99 |
100 | /**
101 | * Returns the logger to use to output logging event.
102 | *
103 | * @return the logger
104 | */
105 | Log getLog();
106 |
107 | /**
108 | * Returns the directory to unpack dependent WARs into if needed.
109 | *
110 | * @return the overlays work directory
111 | */
112 | File getOverlaysWorkDirectory();
113 |
114 | /**
115 | * Returns the archiver manager to use.
116 | *
117 | * @return the archiver manager
118 | */
119 | ArchiverManager getArchiverManager();
120 |
121 | /**
122 | * The maven archive configuration to use.
123 | *
124 | * @return the maven archive configuration
125 | */
126 | MavenArchiveConfiguration getArchive();
127 |
128 | /**
129 | * Returns the Jar archiver needed for archiving classes directory into jar file under WEB-INF/lib.
130 | *
131 | * @return the jar archiver to user
132 | */
133 | JarArchiver getJarArchiver();
134 |
135 | /**
136 | * Returns the output file name mapping to use, if any. Returns null if no file name mapping is set.
137 | *
138 | * @return the output file name mapping or null
139 | */
140 | String getOutputFileNameMapping();
141 |
142 | /**
143 | * Returns the list of filter files to use.
144 | *
145 | * @return a list of filter files
146 | */
147 | List getFilters();
148 |
149 | /**
150 | * Returns the {@link WebappStructure}.
151 | *
152 | * @return the webapp structure
153 | */
154 | WebappStructure getWebappStructure();
155 |
156 | /**
157 | * Returns the list of registered overlays for this session. This list might differ from the one returned by the
158 | * cache; in this case, it means that the project's configuration has changed. The plugin will handle those cases
159 | * nicely but it would be better in general to invoke the clean goal.
160 | *
161 | * @return the list of registered overlays, including the current project
162 | */
163 | List getOwnerIds();
164 |
165 | /**
166 | * Returns the {@link MavenFileFilter} instance to use.
167 | *
168 | * @return the maven file filter to use
169 | * @since 2.1-alpha-2
170 | */
171 | MavenFileFilter getMavenFileFilter();
172 |
173 | /**
174 | * @return {@link List} of {@link FilterWrapper}
175 | * @since 2.1-alpha-2
176 | */
177 | List getFilterWrappers();
178 |
179 | /**
180 | * Specify if the given fileName belongs to the list of extensions that must not be filtered
181 | *
182 | * @param fileName the name of file
183 | * @return true if it should not be filtered, false otherwise
184 | * @since 2.1-alpha-2
185 | */
186 | boolean isNonFilteredExtension( String fileName );
187 |
188 | /**
189 | * @return filtering deployment descriptor.
190 | */
191 | boolean isFilteringDeploymentDescriptors();
192 |
193 | /**
194 | * @return {@link ArtifactFactory}
195 | */
196 | ArtifactFactory getArtifactFactory();
197 |
198 | /**
199 | * Returns the Maven session.
200 | *
201 | * @return the Maven session
202 | * @since 2.2
203 | */
204 | MavenSession getSession();
205 |
206 | /**
207 | * Returns the encoding to use for resources.
208 | *
209 | * @return the resource encoding
210 | * @since 2.3
211 | */
212 | String getResourceEncoding();
213 |
214 | /**
215 | * @return to use jvmChmod rather than forking chmod cli
216 | * @since 2.4
217 | */
218 | boolean isUseJvmChmod();
219 | }
220 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/ArtifactsPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import java.io.IOException;
23 | import java.util.ArrayList;
24 | import java.util.List;
25 | import java.util.Set;
26 |
27 | import org.apache.maven.artifact.Artifact;
28 | import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
29 | import org.apache.maven.plugin.MojoExecutionException;
30 | import cn.wanghaomiao.maven.plugin.seimi.Overlay;
31 | import org.codehaus.plexus.interpolation.InterpolationException;
32 |
33 | /**
34 | * Handles the artifacts that needs to be packaged in the web application.
35 | *
36 | * @author Stephane Nicoll
37 | * @version $Id: ArtifactsPackagingTask.java 1637197 2014-11-06 19:46:57Z khmarbaise $
38 | */
39 | public class ArtifactsPackagingTask
40 | extends AbstractWarPackagingTask
41 | {
42 |
43 | /**
44 | * The {@code tld} path.
45 | */
46 | public static final String TLD_PATH = "WEB-INF/tld/";
47 |
48 | /**
49 | * The {@code services} path.
50 | */
51 | public static final String SERVICES_PATH = "WEB-INF/services/";
52 |
53 | /**
54 | * The {@code modules} path.
55 | */
56 | public static final String MODULES_PATH = "WEB-INF/modules/";
57 |
58 | /**
59 | * The {@code extensions} path.
60 | */
61 | public static final String EXTENSIONS_PATH = "WEB-INF/extensions/";
62 |
63 | private final Set artifacts;
64 |
65 | private final String id;
66 |
67 | /**
68 | * @param artifacts {@link #artifacts}
69 | * @param currentProjectOverlay {@link #id}
70 | */
71 | public ArtifactsPackagingTask( Set artifacts, Overlay currentProjectOverlay )
72 | {
73 | this.artifacts = artifacts;
74 | this.id = currentProjectOverlay.getId();
75 | }
76 |
77 | /**
78 | * {@inheritDoc}
79 | */
80 | public void performPackaging( WarPackagingContext context )
81 | throws MojoExecutionException
82 | {
83 | try
84 | {
85 | final ScopeArtifactFilter filter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME );
86 | final List duplicates = findDuplicates( context, artifacts );
87 |
88 | for ( Artifact artifact : artifacts )
89 | {
90 | String targetFileName = getArtifactFinalName( context, artifact );
91 |
92 | context.getLog().debug( "Processing: " + targetFileName );
93 |
94 | if ( duplicates.contains( targetFileName ) )
95 | {
96 | context.getLog().debug( "Duplicate found: " + targetFileName );
97 | targetFileName = artifact.getGroupId() + "-" + targetFileName;
98 | context.getLog().debug( "Renamed to: " + targetFileName );
99 | }
100 | context.getWebappStructure().registerTargetFileName( artifact, targetFileName );
101 |
102 | if ( !artifact.isOptional() && filter.include( artifact ) )
103 | {
104 | try
105 | {
106 | String type = artifact.getType();
107 | if ( "tld".equals( type ) )
108 | {
109 | copyFile( id, context, artifact.getFile(), TLD_PATH + targetFileName );
110 | }
111 | else if ( "aar".equals( type ) )
112 | {
113 | copyFile( id, context, artifact.getFile(), SERVICES_PATH + targetFileName );
114 | }
115 | else if ( "mar".equals( type ) )
116 | {
117 | copyFile( id, context, artifact.getFile(), MODULES_PATH + targetFileName );
118 | }
119 | else if ( "xar".equals( type ) )
120 | {
121 | copyFile( id, context, artifact.getFile(), EXTENSIONS_PATH + targetFileName );
122 | }
123 | else if ( "jar".equals( type ) || "ejb".equals( type ) || "ejb-client".equals( type )
124 | || "test-jar".equals( type ) || "bundle".equals( type ) )
125 | {
126 | copyFile( id, context, artifact.getFile(), LIB_PATH + targetFileName );
127 | }
128 | else if ( "par".equals( type ) )
129 | {
130 | targetFileName = targetFileName.substring( 0, targetFileName.lastIndexOf( '.' ) ) + ".jar";
131 | copyFile( id, context, artifact.getFile(), LIB_PATH + targetFileName );
132 | }
133 | else if ( "war".equals( type ) )
134 | {
135 | // Nothing to do here, it is an overlay and it's already handled
136 | context.getLog().debug( "war artifacts are handled as overlays, ignoring [" + artifact
137 | + "]" );
138 | }
139 | else if ( "zip".equals( type ) )
140 | {
141 | // Nothing to do here, it is an overlay and it's already handled
142 | context.getLog().debug( "zip artifacts are handled as overlays, ignoring [" + artifact
143 | + "]" );
144 | }
145 | else
146 | {
147 | context.getLog().debug( "Artifact of type [" + type + "] is not supported, ignoring ["
148 | + artifact + "]" );
149 | }
150 | }
151 | catch ( IOException e )
152 | {
153 | throw new MojoExecutionException( "Failed to copy file for artifact [" + artifact + "]", e );
154 | }
155 | }
156 | }
157 | }
158 | catch ( InterpolationException e )
159 | {
160 | throw new MojoExecutionException( e.getMessage(), e );
161 | }
162 | }
163 |
164 | /**
165 | * Searches a set of artifacts for duplicate filenames and returns a list of duplicates.
166 | *
167 | * @param context the packaging context
168 | * @param artifacts set of artifacts
169 | * @return List of duplicated artifacts as bundling file names
170 | */
171 | private List findDuplicates( WarPackagingContext context, Set artifacts )
172 | throws InterpolationException
173 | {
174 | List duplicates = new ArrayList();
175 | List identifiers = new ArrayList();
176 | for ( Artifact artifact : artifacts )
177 | {
178 | String candidate = getArtifactFinalName( context, artifact );
179 | if ( identifiers.contains( candidate ) )
180 | {
181 | duplicates.add( candidate );
182 | }
183 | else
184 | {
185 | identifiers.add( candidate );
186 | }
187 | }
188 | return duplicates;
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/util/PathSet.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.util;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.codehaus.plexus.util.DirectoryScanner;
23 | import org.codehaus.plexus.util.StringUtils;
24 |
25 | import java.io.File;
26 | import java.util.Collection;
27 | import java.util.HashSet;
28 | import java.util.Iterator;
29 | import java.util.LinkedHashSet;
30 | import java.util.Set;
31 |
32 | /**
33 | * Set of file's paths.
34 | *
35 | * The class extends functionality of a "normal" set of strings by a process of the paths normalization. All paths are
36 | * converted to unix form (slashes) and they don't start with starting /.
37 | *
38 | * @author Piotr Tabor
39 | * @version $Id: PathSet.java 1637197 2014-11-06 19:46:57Z khmarbaise $
40 | */
41 |
42 | public class PathSet
43 | implements Iterable
44 | {
45 |
46 | /**
47 | * Set of normalized paths
48 | */
49 | private Set pathsSet = new LinkedHashSet();
50 |
51 | /**
52 | * The method normalizes the path.
53 | *
54 | *
55 | * - changes directory separator to unix's separator(/)
56 | * - deletes all trailing slashes
57 | *
58 | *
59 | * @param path to normalization
60 | * @return normalized path
61 | */
62 | protected String normalizeFilePath( String path )
63 | {
64 | return normalizeFilePathStatic( path );
65 | }
66 |
67 | /*-------------------- Business interface ------------------------------*/
68 |
69 | /**
70 | * Creates an empty paths set
71 | */
72 | public PathSet()
73 | {
74 | /* Empty default constructor */
75 | }
76 |
77 | /**
78 | * Creates paths set and normalizate and adds all 'paths'. The source 'paths' will not be changed
79 | *
80 | * @param paths to be added
81 | */
82 | public PathSet( Collection paths )
83 | {
84 | addAll( paths );
85 | }
86 |
87 | /**
88 | * Creates paths set and normalizate and adds all 'paths'. The source 'paths' will not be changed
89 | *
90 | * @param paths to be added
91 | */
92 | public PathSet( String[] paths )
93 | {
94 | addAll( paths );
95 | }
96 |
97 | /**
98 | * Normalizes and adds given path to the set.
99 | *
100 | * @param path to be added
101 | */
102 | public void add( String path )
103 | {
104 | pathsSet.add( normalizeFilePath( path ) );
105 | }
106 |
107 | /**
108 | * Normalizes and adds given paths (collection of strings) to the set. The source collection will not be changed
109 | *
110 | * @param paths - collection of strings to be added
111 | * @param prefix added to all given paths
112 | */
113 | public void addAll( Collection paths, String prefix )
114 | {
115 | for ( String val : paths )
116 | {
117 | add( prefix + val );
118 | }
119 | }
120 |
121 | /**
122 | * Normalizes and adds given paths to the set. The source collection will not be changed
123 | *
124 | * @param paths to be added
125 | * @param prefix added to all given paths
126 | */
127 | public void addAll( String[] paths, String prefix )
128 | {
129 | for ( String val : paths )
130 | {
131 | add( prefix + val );
132 | }
133 | }
134 |
135 | /**
136 | * Adds given paths to the set. The source collection will not be changed
137 | *
138 | * @param paths to be added
139 | * @param prefix added to all given paths
140 | */
141 | public void addAll( PathSet paths, String prefix )
142 | {
143 | for ( String path : paths )
144 | {
145 | add( prefix + path );
146 | }
147 | }
148 |
149 | /**
150 | * Normalizes and adds given paths (collection of strings) to the set. The source collection will not be changed
151 | *
152 | * @param paths - collection of strings to be added
153 | */
154 | public void addAll( Collection paths )
155 | {
156 | addAll( paths, "" );
157 | }
158 |
159 | /**
160 | * Normalizes and adds given paths to the set. The source collection will not be changed
161 | *
162 | * @param paths to be added
163 | */
164 | public void addAll( String[] paths )
165 | {
166 | addAll( paths, "" );
167 | }
168 |
169 | /**
170 | * Adds given paths to the set. The source collection will not be changed
171 | *
172 | * @param paths to be added
173 | */
174 | public void addAll( PathSet paths )
175 | {
176 | addAll( paths, "" );
177 | }
178 |
179 | /**
180 | * Checks if the set constains given path. The path is normalized before check.
181 | *
182 | * @param path we are looking for in the set.
183 | * @return information if the set constains the path.
184 | */
185 | public boolean contains( String path )
186 | {
187 | return pathsSet.contains( normalizeFilePath( path ) );
188 | }
189 |
190 | /**
191 | * Removes the specified path if it exists.
192 | *
193 | * @param path the path to remove
194 | * @return true if the path was removed, false if it did not existed
195 | */
196 | boolean remove( String path )
197 | {
198 | final String normalizedPath = normalizeFilePath( path );
199 | return pathsSet.remove( normalizedPath );
200 |
201 | }
202 |
203 | /**
204 | * Returns iterator of normalized paths (strings)
205 | *
206 | * @return iterator of normalized paths (strings)
207 | */
208 | public Iterator iterator()
209 | {
210 | return pathsSet.iterator();
211 | }
212 |
213 | /**
214 | * @return {@link #pathsSet}
215 | */
216 | public Collection paths()
217 | {
218 | return pathsSet;
219 | }
220 |
221 | /**
222 | * Adds given prefix to all paths in the set.
223 | *
224 | * The prefix should be ended by '/'. The generated paths are normalized.
225 | *
226 | * @param prefix to be added to all items
227 | */
228 | public void addPrefix( String prefix )
229 | {
230 | final Set newSet = new HashSet();
231 | for ( String path : pathsSet )
232 | {
233 | newSet.add( normalizeFilePath( prefix + path ) );
234 | }
235 | pathsSet = newSet;
236 | }
237 |
238 | /**
239 | * Returns count of the paths in the set
240 | *
241 | * @return count of the paths in the set
242 | */
243 | public int size()
244 | {
245 | return pathsSet.size();
246 | }
247 |
248 | /**
249 | * Adds to the set all files in the given directory
250 | *
251 | * @param directory that will be searched for file's paths to add
252 | * @param prefix to be added to all found files
253 | */
254 | public void addAllFilesInDirectory( File directory, String prefix )
255 | {
256 | DirectoryScanner scanner = new DirectoryScanner();
257 | scanner.setBasedir( directory );
258 | scanner.scan();
259 | addAll( scanner.getIncludedFiles(), prefix );
260 | }
261 |
262 | /*-------------------- Universal static mathods ------------------------*/
263 | /**
264 | * The method normalizes the path.
265 | *
266 | *
267 | * - changes directory separator to unix's separator(/)
268 | * - deletes all trailing slashes
269 | *
270 | *
271 | * @param path to normalization
272 | * @return normalized path
273 | */
274 | public static String normalizeFilePathStatic( String path )
275 | {
276 | return trimTrailingSlashes( StringUtils.replace( path, '\\', '/' ) );
277 | }
278 |
279 | /**
280 | * The method deletes all trailing slashes from the given string
281 | *
282 | * @param str a string
283 | * @return trimed string
284 | */
285 | public static String trimTrailingSlashes( String str )
286 | {
287 | int i;
288 | for ( i = 0; i < str.length() && str.charAt( i ) == '/'; i++ )
289 | {
290 | // just calculate i
291 | }
292 | return str.substring( i );
293 | }
294 |
295 | }
296 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/overlay/OverlayManager.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.overlay;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import java.util.ArrayList;
23 | import java.util.Arrays;
24 | import java.util.List;
25 | import java.util.ListIterator;
26 | import java.util.Set;
27 |
28 | import org.apache.maven.artifact.Artifact;
29 | import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
30 | import cn.wanghaomiao.maven.plugin.seimi.Overlay;
31 | import org.apache.maven.project.MavenProject;
32 | import org.codehaus.plexus.util.StringUtils;
33 |
34 | /**
35 | * Manages the overlays.
36 | *
37 | * @author Stephane Nicoll
38 | * @version $Id: OverlayManager.java 1636820 2014-11-05 08:27:25Z khmarbaise $
39 | */
40 | public class OverlayManager
41 | {
42 | private final List overlays;
43 |
44 | private final MavenProject project;
45 |
46 | private final List artifactsOverlays;
47 |
48 | /**
49 | * Creates a manager with the specified overlays.
50 | *
51 | * Note that the list is potentially updated by the manager so a new list is created based on the overlays.
52 | *
53 | * @param overlays the overlays
54 | * @param project the maven project
55 | * @param defaultIncludes the default includes to use
56 | * @param defaultExcludes the default excludes to use
57 | * @param currentProjectOverlay the overlay for the current project
58 | * @throws InvalidOverlayConfigurationException if the config is invalid
59 | */
60 | public OverlayManager( List overlays, MavenProject project, String defaultIncludes,
61 | String defaultExcludes, Overlay currentProjectOverlay )
62 | throws InvalidOverlayConfigurationException
63 | {
64 | this.overlays = new ArrayList();
65 | if ( overlays != null )
66 | {
67 | this.overlays.addAll( overlays );
68 | }
69 | this.project = project;
70 |
71 | this.artifactsOverlays = getOverlaysAsArtifacts();
72 |
73 | // Initialize
74 | initialize( defaultIncludes, defaultExcludes, currentProjectOverlay );
75 |
76 | }
77 |
78 | /**
79 | * Returns the resolved overlays.
80 | *
81 | * @return the overlays
82 | */
83 | public List getOverlays()
84 | {
85 | return overlays;
86 | }
87 |
88 | /**
89 | * Returns the id of the resolved overlays.
90 | *
91 | * @return the overlay ids
92 | */
93 | public List getOverlayIds()
94 | {
95 | final List result = new ArrayList();
96 | for ( Overlay overlay : overlays )
97 | {
98 | result.add( overlay.getId() );
99 | }
100 | return result;
101 |
102 | }
103 |
104 | /**
105 | * Initializes the manager and validates the overlays configuration.
106 | *
107 | * @param defaultIncludes the default includes to use
108 | * @param defaultExcludes the default excludes to use
109 | * @param currentProjectOverlay the overlay for the current project
110 | * @throws InvalidOverlayConfigurationException if the configuration is invalid
111 | */
112 | void initialize( String defaultIncludes, String defaultExcludes, Overlay currentProjectOverlay )
113 | throws InvalidOverlayConfigurationException
114 | {
115 |
116 | // Build the list of configured artifacts and makes sure that each overlay
117 | // refer to a valid artifact
118 | final List configuredWarArtifacts = new ArrayList();
119 | final ListIterator it = overlays.listIterator();
120 | while ( it.hasNext() )
121 | {
122 | Overlay overlay = it.next();
123 | if ( overlay == null )
124 | {
125 | throw new InvalidOverlayConfigurationException( "overlay could not be null." );
126 | }
127 | // If it's the current project, return the project instance
128 | if ( overlay.isCurrentProject() )
129 | {
130 | overlay = currentProjectOverlay;
131 | it.set( overlay );
132 | }
133 | // default includes/excludes - only if the overlay uses the default settings
134 | if ( Arrays.equals( Overlay.DEFAULT_INCLUDES, overlay.getIncludes() )
135 | && Arrays.equals( Overlay.DEFAULT_EXCLUDES, overlay.getExcludes() ) )
136 | {
137 | overlay.setIncludes( defaultIncludes );
138 | overlay.setExcludes( defaultExcludes );
139 | }
140 |
141 | final Artifact artifact = getAssociatedArtifact( overlay );
142 | if ( artifact != null )
143 | {
144 | configuredWarArtifacts.add( artifact );
145 | overlay.setArtifact( artifact );
146 | }
147 | }
148 |
149 | // Build the list of missing overlays
150 | for ( Artifact artifact : artifactsOverlays )
151 | {
152 | if ( !configuredWarArtifacts.contains( artifact ) )
153 | {
154 | // Add a default overlay for the given artifact which will be applied after
155 | // the ones that have been configured
156 | overlays.add( new DefaultOverlay( artifact, defaultIncludes, defaultExcludes ) );
157 | }
158 | }
159 |
160 | // Final validation, make sure that the current project is in there. Otherwise add it first
161 | for ( Overlay overlay : overlays )
162 | {
163 | if ( overlay.equals( currentProjectOverlay ) )
164 | {
165 | return;
166 | }
167 | }
168 | overlays.add( 0, currentProjectOverlay );
169 | }
170 |
171 | /**
172 | * Returns the Artifact associated to the specified overlay.
173 | *
174 | * If the overlay defines the current project, null is returned. If no artifact could not be found for the
175 | * overlay a InvalidOverlayConfigurationException is thrown.
176 | *
177 | * @param overlay an overlay
178 | * @return the artifact associated to the overlay
179 | * @throws InvalidOverlayConfigurationException if the overlay does not have an
180 | * associated artifact
181 | */
182 | Artifact getAssociatedArtifact( final Overlay overlay )
183 | throws InvalidOverlayConfigurationException
184 | {
185 | if ( overlay.isCurrentProject() )
186 | {
187 | return null;
188 | }
189 |
190 | for ( Artifact artifact : artifactsOverlays )
191 | {
192 | // Handle classifier dependencies properly (clash management)
193 | if ( compareOverlayWithArtifact( overlay, artifact ) )
194 | {
195 | return artifact;
196 | }
197 | }
198 |
199 | // maybe its a project dependencies zip or an other type
200 | @SuppressWarnings( "unchecked" )
201 | Set projectArtifacts = this.project.getDependencyArtifacts();
202 | if ( projectArtifacts != null )
203 | {
204 | for ( Artifact artifact : projectArtifacts )
205 | {
206 | if ( compareOverlayWithArtifact( overlay, artifact ) )
207 | {
208 | return artifact;
209 | }
210 | }
211 | }
212 | // CHECKSTYLE_OFF: LineLength
213 | throw new InvalidOverlayConfigurationException( "overlay [" + overlay + "] is not a dependency of the project." );
214 | // CHECKSTYLE_ON: LineLength
215 |
216 | }
217 |
218 | /**
219 | * Compare groupId && artifactId && type && classifier.
220 | *
221 | * @param overlay the overlay
222 | * @param artifact the artifact
223 | * @return boolean true if equals
224 | */
225 | private boolean compareOverlayWithArtifact( Overlay overlay, Artifact artifact )
226 | {
227 | return ( StringUtils.equals( overlay.getGroupId(), artifact.getGroupId() )
228 | && StringUtils.equals( overlay.getArtifactId(), artifact.getArtifactId() )
229 | && StringUtils.equals( overlay.getType(), artifact.getType() )
230 | // MWAR-241 Make sure to treat null and "" as equal when comparing the classifier
231 | && StringUtils.equals( StringUtils.defaultString( overlay.getClassifier() ),
232 | StringUtils.defaultString( artifact.getClassifier() ) ) );
233 | }
234 |
235 | /**
236 | * Returns a list of WAR {@link org.apache.maven.artifact.Artifact} describing the overlays of the current project.
237 | *
238 | * @return the overlays as artifacts objects
239 | */
240 | private List getOverlaysAsArtifacts()
241 | {
242 | ScopeArtifactFilter filter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME );
243 | @SuppressWarnings( "unchecked" )
244 | final Set artifacts = project.getArtifacts();
245 |
246 | final List result = new ArrayList();
247 | for ( Artifact artifact : artifacts )
248 | {
249 | if ( !artifact.isOptional() && filter.include( artifact ) && ( "war".equals( artifact.getType() ) ) )
250 | {
251 | result.add( artifact );
252 | }
253 | }
254 | return result;
255 | }
256 | }
257 |
--------------------------------------------------------------------------------
/src/main/resources/template/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | SEIMI_HOME=$(cd `dirname $0`; cd ..; pwd)
3 | #https://github.com/rudimeier/bash_ini_parser
4 | function read_ini()
5 | {
6 | S_SECTION=$2; S_ITEM=$3
7 | # Be strict with the prefix, since it's going to be run through eval
8 | function check_prefix()
9 | {
10 | if ! [[ "${VARNAME_PREFIX}" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] ;then
11 | echo "read_ini: invalid prefix '${VARNAME_PREFIX}'" >&2
12 | return 1
13 | fi
14 | }
15 | function check_ini_file()
16 | {
17 | if [ ! -r "$INI_FILE" ] ;then
18 | echo "read_ini: '${INI_FILE}' doesn't exist or not" \
19 | "readable" >&2
20 | return 1
21 | fi
22 | }
23 | # enable some optional shell behavior (shopt)
24 | function pollute_bash()
25 | {
26 | if ! shopt -q extglob ;then
27 | SWITCH_SHOPT="${SWITCH_SHOPT} extglob"
28 | fi
29 | if ! shopt -q nocasematch ;then
30 | SWITCH_SHOPT="${SWITCH_SHOPT} nocasematch"
31 | fi
32 | shopt -q -s ${SWITCH_SHOPT}
33 | }
34 | # unset all local functions and restore shopt settings before returning
35 | # from read_ini()
36 | function cleanup_bash()
37 | {
38 | shopt -q -u ${SWITCH_SHOPT}
39 | unset -f check_prefix check_ini_file pollute_bash cleanup_bash
40 | }
41 | local INI_FILE=""
42 | local INI_SECTION=""
43 | # {{{ START Deal with command line args
44 |
45 | # Set defaults
46 | local BOOLEANS=1
47 | local VARNAME_PREFIX=INI
48 | local CLEAN_ENV=0
49 |
50 | # {{{ START Options
51 |
52 | # Available options:
53 | # --boolean Whether to recognise special boolean values: ie for 'yes', 'true'
54 | # and 'on' return 1; for 'no', 'false' and 'off' return 0. Quoted
55 | # values will be left as strings
56 | # Default: on
57 | #
58 | # --prefix=STRING String to begin all returned variables with (followed by '__').
59 | # Default: INI
60 | #
61 | # First non-option arg is filename, second is section name
62 | while [ $# -gt 0 ]
63 | do
64 | case $1 in
65 | --clean | -c )
66 | CLEAN_ENV=1
67 | ;;
68 | --booleans | -b )
69 | shift
70 | BOOLEANS=$1
71 | ;;
72 | --prefix | -p )
73 | shift
74 | VARNAME_PREFIX=$1
75 | ;;
76 | * )
77 | if [ -z "$INI_FILE" ]
78 | then
79 | INI_FILE=$1
80 | else
81 | if [ -z "$INI_SECTION" ]
82 | then
83 | INI_SECTION=$1
84 | fi
85 | fi
86 | ;;
87 | esac
88 | shift
89 | done
90 | if [ -z "$INI_FILE" ] && [ "${CLEAN_ENV}" = 0 ] ;then
91 | echo -e "Usage: read_ini [-c] [-b 0| -b 1]] [-p PREFIX] FILE"\
92 | "[SECTION]\n or read_ini -c [-p PREFIX]" >&2
93 | cleanup_bash
94 | return 1
95 | fi
96 | if ! check_prefix ;then
97 | cleanup_bash
98 | return 1
99 | fi
100 | local INI_ALL_VARNAME="${VARNAME_PREFIX}__ALL_VARS"
101 | local INI_ALL_SECTION="${VARNAME_PREFIX}__ALL_SECTIONS"
102 | local INI_NUMSECTIONS_VARNAME="${VARNAME_PREFIX}__NUMSECTIONS"
103 | if [ "${CLEAN_ENV}" = 1 ] ;then
104 | eval unset "\$${INI_ALL_VARNAME}"
105 | fi
106 | unset ${INI_ALL_VARNAME}
107 | unset ${INI_ALL_SECTION}
108 | unset ${INI_NUMSECTIONS_VARNAME}
109 | if [ -z "$INI_FILE" ] ;then
110 | cleanup_bash
111 | return 0
112 | fi
113 | if ! check_ini_file ;then
114 | cleanup_bash
115 | return 1
116 | fi
117 | # Sanitise BOOLEANS - interpret "0" as 0, anything else as 1
118 | if [ "$BOOLEANS" != "0" ]
119 | then
120 | BOOLEANS=1
121 | fi
122 | # }}} END Options
123 | # }}} END Deal with command line args
124 | local LINE_NUM=0
125 | local SECTIONS_NUM=0
126 | local SECTION=""
127 | # IFS is used in "read" and we want to switch it within the loop
128 | local IFS=$' \t\n'
129 | local IFS_OLD="${IFS}"
130 | # we need some optional shell behavior (shopt) but want to restore
131 | # current settings before returning
132 | local SWITCH_SHOPT=""
133 | pollute_bash
134 | TARGET_VAR=${VARNAME_PREFIX}__${S_SECTION}__${S_ITEM}
135 | while read -r line || [ -n "$line" ]
136 | do
137 | ((LINE_NUM++))
138 | # Skip blank lines and comments
139 | if [ -z "$line" -o "${line:0:1}" = ";" -o "${line:0:1}" = "#" ]
140 | then
141 | continue
142 | fi
143 | # Section marker?
144 | if [[ "${line}" =~ ^\[[a-zA-Z0-9_]{1,}\]$ ]]
145 | then
146 | # Set SECTION var to name of section (strip [ and ] from section marker)
147 | SECTION="${line#[}"
148 | SECTION="${SECTION%]}"
149 | eval "${INI_ALL_SECTION}=\"\${${INI_ALL_SECTION}# } $SECTION\""
150 | ((SECTIONS_NUM++))
151 | continue
152 | fi
153 | # Are we getting only a specific section? And are we currently in it?
154 | if [ ! -z "$INI_SECTION" ]
155 | then
156 | if [ "$SECTION" != "$INI_SECTION" ]
157 | then
158 | continue
159 | fi
160 | fi
161 | # Valid var/value line? (check for variable name and then '=')
162 | if ! [[ "${line}" =~ ^[a-zA-Z0-9._]{1,}[[:space:]]*= ]]
163 | then
164 | echo "Error: Invalid line:" >&2
165 | echo " ${LINE_NUM}: $line" >&2
166 | cleanup_bash
167 | return 1
168 | fi
169 | # split line at "=" sign
170 | IFS="="
171 | read -r VAR VAL <<< "${line}"
172 | IFS="${IFS_OLD}"
173 |
174 | # delete spaces around the equal sign (using extglob)
175 | VAR="${VAR%%+([[:space:]])}"
176 | VAL="${VAL##+([[:space:]])}"
177 | VAR=$(echo $VAR)
178 | # Construct variable name:
179 | # ${VARNAME_PREFIX}__$SECTION__$VAR
180 | # Or if not in a section:
181 | # ${VARNAME_PREFIX}__$VAR
182 | # In both cases, full stops ('.') are replaced with underscores ('_')
183 | if [ -z "$SECTION" ]
184 | then
185 | VARNAME=${VARNAME_PREFIX}__${VAR//./_}
186 | else
187 | VARNAME=${VARNAME_PREFIX}__${SECTION}__${VAR//./_}
188 | fi
189 | eval "${INI_ALL_VARNAME}=\"\${${INI_ALL_VARNAME}# } ${VARNAME}\""
190 |
191 | if [[ "${VAL}" =~ ^\".*\"$ ]]
192 | then
193 | # remove existing double quotes
194 | VAL="${VAL##\"}"
195 | VAL="${VAL%%\"}"
196 | elif [[ "${VAL}" =~ ^\'.*\'$ ]]
197 | then
198 | # remove existing single quotes
199 | VAL="${VAL##\'}"
200 | VAL="${VAL%%\'}"
201 | elif [ "$BOOLEANS" = 1 ]
202 | then
203 | # Value is not enclosed in quotes
204 | # Booleans processing is switched on, check for special boolean
205 | # values and convert
206 | # here we compare case insensitive because
207 | # "shopt nocasematch"
208 | case "$VAL" in
209 | yes | true | on )
210 | VAL=1
211 | ;;
212 | no | false | off )
213 | VAL=0
214 | ;;
215 | esac
216 | fi
217 | # enclose the value in single quotes and escape any
218 | # single quotes and backslashes that may be in the value
219 | VAL="${VAL//\\/\\\\}"
220 | #VAL="\$'${VAL//\'/\'}'"
221 | if [[ $VARNAME = $TARGET_VAR ]]
222 | then
223 | echo "${VAL}"
224 | break
225 | fi
226 | done <"${INI_FILE}"
227 | cleanup_bash
228 | }
229 | function usage(){
230 | cat<$SEIMI_STDOUT 2>&1 &
253 | PID=`echo $!`
254 | if [ -d "/proc/$PID" ]; then
255 | echo $!>"$SEIMI_HOME/.seimicrawler.lock.pid"
256 | echo "[Info]SeimiCrawler started,pid: $PID"
257 | else
258 | echo "[Error]SeimiCrawler start failed ,you can see more info in $SEIMI_STDOUT."
259 | fi
260 | exit 0
261 | }
262 |
263 | function stop(){
264 | if [ -f "$SEIMI_HOME/.seimicrawler.lock.pid" ]; then
265 | echo "SeimiCrawler pid file is ok."
266 | else
267 | echo "No SeimiCrawler instance is alive,home dir: $SEIMI_HOME"
268 | exit 0
269 | fi
270 | pid=$(cat $SEIMI_HOME/.seimicrawler.lock.pid)
271 | if [ ! -d "/proc/$pid" ]; then
272 | echo "No SeimiCrawler instance is running,pid:$pid"
273 | rm "$SEIMI_HOME/.seimicrawler.lock.pid"
274 | exit 0
275 | else
276 | kill $pid
277 | if [ $? -eq 0 ]; then
278 | echo "Stop current SeimiCrawler instance,pid:$pid"
279 | rm "$SEIMI_HOME/.seimicrawler.lock.pid"
280 | exit 0
281 | else
282 | echo "Stop current SeimiCrawler instance failed,pid:$pid"
283 | fi
284 | fi
285 | rm "$SEIMI_HOME/.seimicrawler.lock.pid"
286 | exit 0
287 | }
288 | for arg ;do
289 | case "$arg" in
290 | help) usage ;;
291 | start) start;;
292 | stop) stop;;
293 | esac
294 | done
295 |
296 | usage
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/Overlay.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.artifact.Artifact;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Arrays;
26 | import java.util.List;
27 |
28 | /**
29 | * An overlay is a skeleton WAR added to another WAR project in order to inject a functionality, resources or any other
30 | * shared component.
31 | *
32 | * Note that a particular WAR dependency can be added multiple times as an overlay with different includes/excludes
33 | * filter; this allows building a fine grained overwriting policy.
34 | *
35 | * The current project can also be described as an overlay and can not be specified twice. An overlay with no groupId
36 | * and no artifactId represents the current project.
37 | *
38 | * @author Stephane Nicoll
39 | * @version $Id: Overlay.java 1637197 2014-11-06 19:46:57Z khmarbaise $
40 | */
41 | public class Overlay
42 | {
43 |
44 | /**
45 | * The list of default includes.
46 | */
47 | public static final String[] DEFAULT_INCLUDES = new String[] { "**/**" };
48 |
49 | /**
50 | * The list of default excludes.
51 | */
52 | public static final String[] DEFAULT_EXCLUDES = new String[] { "META-INF/MANIFEST.MF" };
53 |
54 | private String id;
55 |
56 | private String groupId;
57 |
58 | private String artifactId;
59 |
60 | private String classifier = null;
61 |
62 | private String[] includes = DEFAULT_INCLUDES;
63 |
64 | private String[] excludes = DEFAULT_EXCLUDES;
65 |
66 | private boolean filtered = false;
67 |
68 | private boolean skip = false;
69 |
70 | private Artifact artifact;
71 |
72 | private String targetPath;
73 |
74 | /** default overlay type is war */
75 | private String type = "war";
76 |
77 | /**
78 | * Create instance.
79 | */
80 | public Overlay()
81 | {
82 | super();
83 | }
84 |
85 | /**
86 | * @param groupId {@link #groupId}
87 | * @param artifactId {@link #artifactId}
88 | */
89 | public Overlay( String groupId, String artifactId )
90 | {
91 | this();
92 | this.groupId = groupId;
93 | this.artifactId = artifactId;
94 | }
95 |
96 | /**
97 | * Specify whether this overlay represents the current project or not.
98 | *
99 | * @return true if the overlay represents the current project, false otherwise
100 | */
101 | public boolean isCurrentProject()
102 | {
103 | return ( groupId == null && artifactId == null );
104 | }
105 |
106 | /**
107 | * @return {@link Overlay} instance.
108 | */
109 | public static Overlay createInstance()
110 | {
111 | Overlay overlay = new Overlay();
112 | overlay.setId( "currentBuild" );
113 | return overlay;
114 | }
115 |
116 | // Getters and Setters
117 |
118 | /**
119 | * @return The id.
120 | */
121 | public String getId()
122 | {
123 | if ( id == null )
124 | {
125 | final StringBuilder sb = new StringBuilder();
126 | sb.append( getGroupId() ).append( ":" ).append( getArtifactId() );
127 | if ( getClassifier() != null )
128 | {
129 | sb.append( ":" ).append( getClassifier() );
130 | }
131 | id = sb.toString();
132 | }
133 | return id;
134 | }
135 |
136 | /**
137 | * @param id The id.
138 | */
139 | public void setId( String id )
140 | {
141 | this.id = id;
142 | }
143 |
144 | /**
145 | * @return {@link #groupId}
146 | */
147 | public String getGroupId()
148 | {
149 | return groupId;
150 | }
151 |
152 | /**
153 | * @param groupId {@link #groupId}
154 | */
155 | public void setGroupId( String groupId )
156 | {
157 | this.groupId = groupId;
158 | }
159 |
160 | /**
161 | * @return {@link #artifactId}
162 | */
163 | public String getArtifactId()
164 | {
165 | return artifactId;
166 | }
167 |
168 | /**
169 | * @param artifactId {@link #artifactId}
170 | */
171 | public void setArtifactId( String artifactId )
172 | {
173 | this.artifactId = artifactId;
174 | }
175 |
176 | /**
177 | * @return {@link #classifier}
178 | */
179 | public String getClassifier()
180 | {
181 | return classifier;
182 | }
183 |
184 | /**
185 | * @param classifier {@link #classifier}
186 | */
187 | public void setClassifier( String classifier )
188 | {
189 | this.classifier = classifier;
190 | }
191 |
192 | /**
193 | * @return {@link #includes}
194 | */
195 | public String[] getIncludes()
196 | {
197 | return includes;
198 | }
199 |
200 | /**
201 | * @param includes {@link #includes}
202 | */
203 | public void setIncludes( String includes )
204 | {
205 | this.includes = parse( includes );
206 | }
207 |
208 | /**
209 | * @param includes {@link #includes}
210 | */
211 | public void setIncludes( String[] includes )
212 | {
213 | this.includes = includes;
214 | }
215 |
216 | /**
217 | * @return {@link #excludes}
218 | */
219 | public String[] getExcludes()
220 | {
221 | return excludes;
222 | }
223 |
224 | /**
225 | * @param excludes {@link #excludes}
226 | */
227 | public void setExcludes( String excludes )
228 | {
229 | this.excludes = parse( excludes );
230 | }
231 |
232 | /**
233 | * @param excludes {@link #excludes}
234 | */
235 | public void setExcludes( String[] excludes )
236 | {
237 | this.excludes = excludes;
238 | }
239 |
240 | /**
241 | * @return {@link #filtered}
242 | */
243 | public boolean isFiltered()
244 | {
245 | return filtered;
246 | }
247 |
248 | /**
249 | * @param filtered {@link #filtered}
250 | */
251 | public void setFiltered( boolean filtered )
252 | {
253 | this.filtered = filtered;
254 | }
255 |
256 | /**
257 | * @return {@link #skip}
258 | */
259 | public boolean shouldSkip()
260 | {
261 | return skip;
262 | }
263 |
264 | /**
265 | * @param skip {@link #skip}
266 | */
267 | public void setSkip( boolean skip )
268 | {
269 | this.skip = skip;
270 | }
271 |
272 | /**
273 | * @return {@link #artifact}
274 | */
275 | public Artifact getArtifact()
276 | {
277 | return artifact;
278 | }
279 |
280 | /**
281 | * @param artifact {@link #artifact}
282 | */
283 | public void setArtifact( Artifact artifact )
284 | {
285 | this.artifact = artifact;
286 | }
287 |
288 | /**
289 | * @return {@link #targetPath}
290 | */
291 | public String getTargetPath()
292 | {
293 | return targetPath;
294 | }
295 |
296 | /**
297 | * @param targetPath {@link #targetPath}
298 | */
299 | public void setTargetPath( String targetPath )
300 | {
301 | this.targetPath = targetPath;
302 | }
303 |
304 | /**
305 | * @return {@link #type}
306 | */
307 | public String getType()
308 | {
309 | return type;
310 | }
311 |
312 | /**
313 | * @param type {@link #type}
314 | */
315 | public void setType( String type )
316 | {
317 | this.type = type;
318 | }
319 |
320 | /**
321 | * {@inheritDoc}
322 | */
323 | public String toString()
324 | {
325 | return " id " + getId();
326 | }
327 |
328 | /**
329 | * {@inheritDoc}
330 | */
331 | public boolean equals( Object o )
332 | {
333 | if ( this == o )
334 | {
335 | return true;
336 | }
337 | if ( o == null || getClass() != o.getClass() )
338 | {
339 | return false;
340 | }
341 |
342 | Overlay overlay = (Overlay) o;
343 |
344 | if ( excludes != null ? !Arrays.equals( excludes, overlay.excludes ) : overlay.excludes != null )
345 | {
346 | return false;
347 | }
348 | if ( getId() != null ? !getId().equals( overlay.getId() ) : overlay.getId() != null )
349 | {
350 | return false;
351 | }
352 | if ( includes != null ? !Arrays.equals( includes, overlay.includes ) : overlay.includes != null )
353 | {
354 | return false;
355 | }
356 |
357 | return true;
358 | }
359 |
360 | /**
361 | * {@inheritDoc}
362 | */
363 | public int hashCode()
364 | {
365 | int result;
366 | result = ( getId() != null ? getId().hashCode() : 0 );
367 | result = 31 * result + ( includes != null ? includes.hashCode() : 0 );
368 | result = 31 * result + ( excludes != null ? excludes.hashCode() : 0 );
369 | return result;
370 | }
371 |
372 | private String[] parse( String s )
373 | {
374 | final List result = new ArrayList();
375 | if ( s == null )
376 | {
377 | return result.toArray( new String[result.size()] );
378 | }
379 | else
380 | {
381 | String[] tokens = s.split( "," );
382 | for ( String token : tokens )
383 | {
384 | result.add( token.trim() );
385 | }
386 | return result.toArray( new String[result.size()] );
387 | }
388 | }
389 |
390 | }
391 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/DependenciesAnalysisPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import cn.wanghaomiao.maven.plugin.seimi.util.WebappStructure;
23 | import org.apache.maven.artifact.Artifact;
24 | import org.apache.maven.model.Dependency;
25 | import org.apache.maven.plugin.MojoExecutionException;
26 | import org.apache.maven.plugin.MojoFailureException;
27 |
28 | import java.io.File;
29 |
30 | /**
31 | * Analyzes the dependencies of the project with its previous state and update the target directory accordingly.
32 | *
33 | * @author Stephane Nicoll
34 | * @version $Id: DependenciesAnalysisPackagingTask.java 1637197 2014-11-06 19:46:57Z khmarbaise $
35 | */
36 | public class DependenciesAnalysisPackagingTask
37 | extends AbstractWarPackagingTask
38 | {
39 |
40 | /**
41 | * {@inheritDoc}
42 | */
43 | public void performPackaging( final WarPackagingContext context )
44 | throws MojoExecutionException, MojoFailureException
45 | {
46 |
47 | context.getWebappStructure().analyseDependencies( new DependenciesAnalysisCallbackImpl( context ) );
48 |
49 | }
50 |
51 | /**
52 | * {@inheritDoc}
53 | */
54 | protected void handleDependency( WarPackagingContext context, Dependency dependency, String notBundledMessage,
55 | String warOrZipMessage, String standardMessage, boolean removeFile )
56 | {
57 | if ( Artifact.SCOPE_PROVIDED.equals( dependency.getScope() )
58 | || Artifact.SCOPE_TEST.equals( dependency.getScope() ) || dependency.isOptional() )
59 | {
60 | context.getLog().debug( notBundledMessage );
61 | }
62 | else
63 | {
64 | handleDependencyScope( context, dependency, warOrZipMessage, standardMessage, removeFile );
65 | }
66 | }
67 |
68 | /**
69 | * {@inheritDoc}
70 | */
71 | protected void handleDependencyScope( WarPackagingContext context, Dependency dependency, String warOrZipMessage,
72 | String standardMessage, boolean removeFile )
73 | {
74 | if ( "war".equals( dependency.getType() ) || "zip".equals( dependency.getType() ) )
75 | {
76 | context.getLog().warn( warOrZipMessage );
77 | }
78 | else if ( "tld".equals( dependency.getType() ) || "aar".equals( dependency.getType() )
79 | || "mar".equals( dependency.getType() ) || "xar".equals( dependency.getType() )
80 | || "jar".equals( dependency.getType() ) || "ejb".equals( dependency.getType() )
81 | || "ejb-client".equals( dependency.getType() ) || "test-jar".equals( dependency.getType() )
82 | || "par".equals( dependency.getType() ) )
83 | {
84 | context.getLog().info( standardMessage );
85 | if ( removeFile )
86 | {
87 | removeDependency( context, dependency );
88 | }
89 | }
90 | }
91 |
92 | private void removeDependency( WarPackagingContext context, Dependency dependency )
93 | {
94 | final String targetFileName = context.getWebappStructure().getCachedTargetFileName( dependency );
95 | if ( targetFileName != null )
96 | {
97 | final String type = dependency.getType();
98 | File targetFile = null;
99 | if ( "tld".equals( type ) )
100 | {
101 | targetFile = new File( context.getWebappDirectory(), ArtifactsPackagingTask.TLD_PATH + targetFileName );
102 | }
103 | else if ( "aar".equals( type ) )
104 | {
105 | targetFile =
106 | new File( context.getWebappDirectory(), ArtifactsPackagingTask.SERVICES_PATH + targetFileName );
107 | }
108 | else if ( "mar".equals( type ) )
109 | {
110 | targetFile =
111 | new File( context.getWebappDirectory(), ArtifactsPackagingTask.MODULES_PATH + targetFileName );
112 | }
113 | else if ( "xar".equals( type ) )
114 | {
115 | targetFile =
116 | new File( context.getWebappDirectory(), ArtifactsPackagingTask.EXTENSIONS_PATH + targetFileName );
117 | }
118 | else if ( "jar".equals( type ) || "ejb".equals( type ) || "ejb-client".equals( type )
119 | || "test-jar".equals( type ) )
120 | {
121 | targetFile = new File( context.getWebappDirectory(), LIB_PATH + targetFileName );
122 | }
123 | else if ( "par".equals( type ) )
124 | {
125 | String targetFileName2 = targetFileName.substring( 0, targetFileName.lastIndexOf( '.' ) ) + ".jar";
126 | targetFile = new File( context.getWebappDirectory(), LIB_PATH + targetFileName2 );
127 | }
128 |
129 | // now remove
130 | if ( targetFile == null )
131 | {
132 | context.getLog().error( "Could not get file from dependency [" + dependency + "]" );
133 | }
134 | else if ( targetFile.exists() )
135 | {
136 | context.getLog().debug( "Removing file [" + targetFile.getAbsolutePath() + "]" );
137 | targetFile.delete();
138 | }
139 | else
140 | {
141 | context.getLog().warn( "File to remove [" + targetFile.getAbsolutePath() + "] has not been found" );
142 | }
143 | }
144 | else
145 | {
146 | context.getLog().warn( "Could not retrieve the target file name of dependency [" + dependency + "]" );
147 | }
148 | }
149 |
150 | class DependenciesAnalysisCallbackImpl
151 | implements WebappStructure.DependenciesAnalysisCallback
152 | {
153 | private final WarPackagingContext context;
154 |
155 | DependenciesAnalysisCallbackImpl( WarPackagingContext context )
156 | {
157 | this.context = context;
158 | }
159 |
160 | public void unchangedDependency( Dependency dependency )
161 | {
162 | context.getLog().debug( "Dependency [" + dependency + "] has not changed since last build." );
163 | }
164 |
165 | public void newDependency( Dependency dependency )
166 | {
167 | context.getLog().debug( "New dependency [" + dependency + "]." );
168 | }
169 |
170 | public void removedDependency( Dependency dependency )
171 | {
172 | handleDependency( context, dependency, "Dependency [" + dependency
173 | + "] has been removed from the project but it was not bundled anyway.", "Dependency [" + dependency
174 | + "] has been removed from the project. If it was included in the build as an overlay, "
175 | + "consider cleaning the target directory of the project (mvn clean)", "Dependency [" + dependency
176 | + "] has been removed from the project.", true );
177 | }
178 |
179 | public void updatedVersion( Dependency dependency, String previousVersion )
180 | {
181 | handleDependency( context, dependency, "Version of dependency [" + dependency + "] has changed ("
182 | + previousVersion + " -> " + dependency.getVersion()
183 | + ") but it was not bundled anyway.",
184 | "Version of dependency [" + dependency + "] has changed (" + previousVersion + " -> "
185 | + dependency.getVersion() + "). If it was included in the build as an overlay, "
186 | + "consider " + "cleaning the target directory of the project (mvn clean)",
187 | "Version of dependency [" + dependency + "] has changed (" + previousVersion + " -> "
188 | + dependency.getVersion() + ").", true );
189 | }
190 |
191 | public void updatedScope( Dependency dependency, String previousScope )
192 | {
193 | // CHECKSTYLE_OFF: LineLength
194 | if ( Artifact.SCOPE_PROVIDED.equals( dependency.getScope() )
195 | || Artifact.SCOPE_TEST.equals( dependency.getScope() )
196 | && ( !Artifact.SCOPE_PROVIDED.equals( previousScope ) && !Artifact.SCOPE_TEST.equals( previousScope ) ) )
197 | // CHECKSTYLE_ON: LineLength
198 | {
199 | // It's now provided or test so it should be removed
200 | handleDependencyScope( context, dependency, "Scope of dependency [" + dependency + "] has changed ("
201 | + previousScope + " -> " + dependency.getScope()
202 | + "). If it was included in the build as an overlay, "
203 | + "consider cleaning the target directory of the project (mvn clean)", "Scope of dependency ["
204 | + dependency + "] has changed (" + previousScope + " -> " + dependency.getScope() + ").", true );
205 | }
206 |
207 | }
208 |
209 | public void updatedOptionalFlag( Dependency dependency, boolean previousOptional )
210 | {
211 | if ( !previousOptional && dependency.isOptional() )
212 | {
213 | // It wasn't optional but now it is anymore
214 | handleDependency( context, dependency, "Dependency [" + dependency
215 | + "] is now optional but it was not bundled anyway.", "Dependency [" + dependency
216 | + "] is now optional. If it was included in the build as an overlay, "
217 | + "consider cleaning the target directory of the project (mvn clean)", "Dependency [" + dependency
218 | + "] is now optional", true );
219 |
220 | }
221 | }
222 |
223 | public void updatedUnknown( Dependency dependency, Dependency previousDep )
224 | {
225 | handleDependency( context, dependency, "Dependency [" + dependency + "] has changed (was " + previousDep
226 | + ") but it was not bundled anyway.", "Dependency [" + dependency + "] has changed (was " + previousDep
227 | + "). If it was included in the build as an overlay, " + "consider "
228 | + "cleaning the target directory of the project (mvn clean)", "Dependency [" + dependency
229 | + "] has changed (was " + previousDep + ").", true );
230 | }
231 |
232 | }
233 |
234 | }
235 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/SeimiMojo.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi;
2 |
3 | /*
4 | * Apache License Version2.0
5 | */
6 |
7 | import org.apache.maven.archiver.MavenArchiver;
8 | import org.apache.maven.artifact.Artifact;
9 | import org.apache.maven.artifact.DependencyResolutionRequiredException;
10 | import org.apache.maven.plugin.MojoExecutionException;
11 | import org.apache.maven.plugin.MojoFailureException;
12 | import cn.wanghaomiao.maven.plugin.seimi.util.ClassesPackager;
13 | import org.apache.maven.plugins.annotations.Component;
14 | import org.apache.maven.plugins.annotations.LifecyclePhase;
15 | import org.apache.maven.plugins.annotations.Mojo;
16 | import org.apache.maven.plugins.annotations.Parameter;
17 | import org.apache.maven.plugins.annotations.ResolutionScope;
18 | import org.apache.maven.project.MavenProjectHelper;
19 | import org.codehaus.plexus.archiver.Archiver;
20 | import org.codehaus.plexus.archiver.ArchiverException;
21 | import org.codehaus.plexus.archiver.jar.ManifestException;
22 | import org.codehaus.plexus.archiver.war.WarArchiver;
23 | import org.codehaus.plexus.util.FileUtils;
24 | import org.codehaus.plexus.util.StringUtils;
25 |
26 | import java.io.File;
27 | import java.io.IOException;
28 | import java.util.Arrays;
29 |
30 | @Mojo(name = "build", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, requiresDependencyResolution = ResolutionScope.RUNTIME)
31 | public class SeimiMojo extends AbstractWarMojo {
32 | /**
33 | * The directory for build.
34 | */
35 | @Parameter(defaultValue = "${project.build.directory}", required = true)
36 | private String outputDirectory;
37 |
38 | /**
39 | * The name of the final package.
40 | */
41 | @Parameter(defaultValue = "${project.build.finalName}", property = "war.warName", required = true)
42 | private String pkgName;
43 |
44 | /**
45 | * Classifier to add to the generated WAR. If given, the artifact will be an attachment instead. The classifier will
46 | * not be applied to the JAR file of the project - only to the WAR file.
47 | */
48 | @Parameter
49 | private String classifier;
50 |
51 | /**
52 | * The comma separated list of tokens to exclude from the WAR before packaging. This option may be used to implement
53 | * the skinny WAR use case. Note that you can use the Java Regular Expressions engine to include and exclude
54 | * specific pattern using the expression %regex[]. Hint: read the about (?!Pattern).
55 | *
56 | * @since 2.1-alpha-2
57 | */
58 | @Parameter
59 | private String packagingExcludes;
60 |
61 | /**
62 | * The comma separated list of tokens to include in the WAR before packaging. By default everything is included.
63 | * This option may be used to implement the skinny WAR use case. Note that you can use the Java Regular Expressions
64 | * engine to include and exclude specific pattern using the expression %regex[].
65 | *
66 | * @since 2.1-beta-1
67 | */
68 | @Parameter
69 | private String packagingIncludes;
70 |
71 | /**
72 | * The WAR archiver.
73 | */
74 | @Component(role = Archiver.class, hint = "war")
75 | private WarArchiver warArchiver;
76 |
77 | /**
78 | */
79 | @Component
80 | private MavenProjectHelper projectHelper;
81 |
82 | private boolean primaryArtifact = true;
83 |
84 | private boolean failOnMissingWebXml = false;
85 |
86 | /**
87 | * Whether classes (that is the content of the WEB-INF/classes directory) should be attached to the project as an
88 | * additional artifact.
89 | *
90 | * By default the classifier for the additional artifact is 'classes'. You can change it with the
91 | * someclassifier]]> parameter.
92 | *
93 | *
94 | * If this parameter true, another project can depend on the classes by writing something like:
95 | *
96 | *
97 | *
98 | * myGroup
99 | * myArtifact
100 | * myVersion
101 | * classes
102 | * ]]>
103 | *
104 | *
105 | *
106 | *
107 | * @since 2.1-alpha-2
108 | */
109 | @Parameter(defaultValue = "false")
110 | private boolean attachClasses = false;
111 |
112 | /**
113 | * The classifier to use for the attached classes artifact.
114 | *
115 | * @since 2.1-alpha-2
116 | */
117 | @Parameter(defaultValue = "classes")
118 | private String classesClassifier = "classes";
119 |
120 | // ----------------------------------------------------------------------
121 | // Implementation
122 | // ----------------------------------------------------------------------
123 |
124 | /**
125 | * Executes the WarMojo on the current project.
126 | *
127 | * @throws MojoExecutionException if an error occurred while building the webapp
128 | * @throws MojoFailureException if an error.
129 | */
130 | public void execute()
131 | throws MojoExecutionException, MojoFailureException {
132 | File warFile = getTargetWarFile();
133 |
134 | try {
135 | performPackaging(warFile);
136 | } catch (DependencyResolutionRequiredException e) {
137 | throw new MojoExecutionException("Error assembling WAR: " + e.getMessage(), e);
138 | } catch (ManifestException e) {
139 | throw new MojoExecutionException("Error assembling WAR", e);
140 | } catch (IOException e) {
141 | throw new MojoExecutionException("Error assembling WAR", e);
142 | } catch (ArchiverException e) {
143 | throw new MojoExecutionException("Error assembling WAR: " + e.getMessage(), e);
144 | }
145 | }
146 |
147 | /**
148 | * Generates the webapp according to the mode attribute.
149 | *
150 | * @param warFile the target WAR file
151 | * @throws IOException if an error occurred while copying files
152 | * @throws ArchiverException if the archive could not be created
153 | * @throws ManifestException if the manifest could not be created
154 | * @throws DependencyResolutionRequiredException if an error occurred while resolving the dependencies
155 | * @throws MojoExecutionException if the execution failed
156 | * @throws MojoFailureException if a fatal exception occurred
157 | */
158 | private void performPackaging(File warFile)
159 | throws IOException, ManifestException, DependencyResolutionRequiredException, MojoExecutionException,
160 | MojoFailureException {
161 | getLog().info("Packaging app");
162 |
163 | buildExplodedWebapp(getWebappDirectory());
164 |
165 | TemplateTask templateTask = new TemplateTask(getWebappDirectory(),getLog());
166 | templateTask.createBinFile();
167 |
168 | MavenArchiver archiver = new MavenArchiver();
169 |
170 | archiver.setArchiver(warArchiver);
171 |
172 | archiver.setOutputFile(warFile);
173 |
174 | // CHECKSTYLE_OFF: LineLength
175 | getLog().debug("Excluding " + Arrays.asList(getPackagingExcludes()) + " from the generated app archive.");
176 | getLog().debug("Including " + Arrays.asList(getPackagingIncludes()) + " in the generated app archive.");
177 | // CHECKSTYLE_ON: LineLength
178 |
179 | warArchiver.addDirectory(getWebappDirectory(), getPackagingIncludes(), getPackagingExcludes());
180 |
181 | // final File webXmlFile = new File(getWebappDirectory(), "WEB-INF/web.xml");
182 | // if (webXmlFile.exists()) {
183 | // warArchiver.setWebxml(webXmlFile);
184 | // }
185 |
186 | warArchiver.setRecompressAddedZips(isRecompressZippedFiles());
187 |
188 | warArchiver.setIncludeEmptyDirs(isIncludeEmptyDirectories());
189 |
190 | if (!failOnMissingWebXml) {
191 | getLog().debug("Build won't fail if web.xml file is missing.");
192 | warArchiver.setExpectWebXml(false);
193 | }
194 |
195 | // create archive
196 | archiver.createArchive(getSession(), getProject(), getArchive());
197 |
198 | // create the classes to be attached if necessary
199 | if (isAttachClasses()) {
200 | if (isArchiveClasses() && getJarArchiver().getDestFile() != null) {
201 | // special handling in case of archived classes: MWAR-240
202 | File targetClassesFile = getTargetClassesFile();
203 | FileUtils.copyFile(getJarArchiver().getDestFile(), targetClassesFile);
204 | projectHelper.attachArtifact(getProject(), "jar", getClassesClassifier(), targetClassesFile);
205 | } else {
206 | ClassesPackager packager = new ClassesPackager();
207 | final File classesDirectory = packager.getClassesDirectory(getWebappDirectory());
208 | if (classesDirectory.exists()) {
209 | getLog().info("Packaging classes");
210 | packager.packageClasses(classesDirectory, getTargetClassesFile(), getJarArchiver(), getSession(),
211 | getProject(), getArchive());
212 | projectHelper.attachArtifact(getProject(), "jar", getClassesClassifier(), getTargetClassesFile());
213 | }
214 | }
215 | }
216 |
217 | if (this.classifier != null) {
218 | projectHelper.attachArtifact(getProject(), "war", this.classifier, warFile);
219 | } else {
220 | Artifact artifact = getProject().getArtifact();
221 | if (primaryArtifact) {
222 | artifact.setFile(warFile);
223 | } else if (artifact.getFile() == null || artifact.getFile().isDirectory()) {
224 | artifact.setFile(warFile);
225 | }
226 | }
227 | }
228 |
229 | /**
230 | * @param basedir The basedir
231 | * @param finalName The finalName
232 | * @param classifier The classifier.
233 | * @param type The type.
234 | * @return {@link File}
235 | */
236 | protected static File getTargetFile(File basedir, String finalName, String classifier, String type) {
237 | if (classifier == null) {
238 | classifier = "";
239 | } else if (classifier.trim().length() > 0 && !classifier.startsWith("-")) {
240 | classifier = "-" + classifier;
241 | }
242 |
243 | return new File(basedir, finalName + classifier + "." + type);
244 | }
245 |
246 | /**
247 | * @return The war {@link File}
248 | */
249 | protected File getTargetWarFile() {
250 | return getTargetFile(new File(getOutputDirectory()), getPkgName(), getClassifier(), "zip");
251 |
252 | }
253 |
254 | /**
255 | * @return The target class {@link File}
256 | */
257 | protected File getTargetClassesFile() {
258 | return getTargetFile(new File(getOutputDirectory()), getPkgName(), getClassesClassifier(), "jar");
259 | }
260 |
261 | // Getters and Setters
262 |
263 | /**
264 | * @return {@link #classifier}
265 | */
266 | public String getClassifier() {
267 | return classifier;
268 | }
269 |
270 | /**
271 | * @param classifier {@link #classifier}
272 | */
273 | public void setClassifier(String classifier) {
274 | this.classifier = classifier;
275 | }
276 |
277 | /**
278 | * @return The package excludes.
279 | */
280 | public String[] getPackagingExcludes() {
281 | if (StringUtils.isEmpty(packagingExcludes)) {
282 | return new String[0];
283 | } else {
284 | return StringUtils.split(packagingExcludes, ",");
285 | }
286 | }
287 |
288 | /**
289 | * @param packagingExcludes {@link #packagingExcludes}
290 | */
291 | public void setPackagingExcludes(String packagingExcludes) {
292 | this.packagingExcludes = packagingExcludes;
293 | }
294 |
295 | /**
296 | * @return The packaging includes.
297 | */
298 | public String[] getPackagingIncludes() {
299 | if (StringUtils.isEmpty(packagingIncludes)) {
300 | return new String[]{"**"};
301 | } else {
302 | return StringUtils.split(packagingIncludes, ",");
303 | }
304 | }
305 |
306 | /**
307 | * @param packagingIncludes {@link #packagingIncludes}
308 | */
309 | public void setPackagingIncludes(String packagingIncludes) {
310 | this.packagingIncludes = packagingIncludes;
311 | }
312 |
313 | /**
314 | * @return {@link #outputDirectory}
315 | */
316 | public String getOutputDirectory() {
317 | return outputDirectory;
318 | }
319 |
320 | /**
321 | * @param outputDirectory {@link #outputDirectory}
322 | */
323 | public void setOutputDirectory(String outputDirectory) {
324 | this.outputDirectory = outputDirectory;
325 | }
326 |
327 | /**
328 | * @return {@link #pkgName}
329 | */
330 | public String getPkgName() {
331 | return pkgName;
332 | }
333 |
334 | /**
335 | * @param pkgName {@link #pkgName}
336 | */
337 | public void setPkgName(String pkgName) {
338 | this.pkgName = pkgName;
339 | }
340 |
341 | /**
342 | * @return {@link #warArchiver}
343 | */
344 | public WarArchiver getWarArchiver() {
345 | return warArchiver;
346 | }
347 |
348 | /**
349 | * @param warArchiver {@link #warArchiver}
350 | */
351 | public void setWarArchiver(WarArchiver warArchiver) {
352 | this.warArchiver = warArchiver;
353 | }
354 |
355 | /**
356 | * @return {@link #projectHelper}
357 | */
358 | public MavenProjectHelper getProjectHelper() {
359 | return projectHelper;
360 | }
361 |
362 | /**
363 | * @param projectHelper {@link #projectHelper}
364 | */
365 | public void setProjectHelper(MavenProjectHelper projectHelper) {
366 | this.projectHelper = projectHelper;
367 | }
368 |
369 | /**
370 | * @return {@link #primaryArtifact}
371 | */
372 | public boolean isPrimaryArtifact() {
373 | return primaryArtifact;
374 | }
375 |
376 | /**
377 | * @param primaryArtifact {@link #primaryArtifact}
378 | */
379 | public void setPrimaryArtifact(boolean primaryArtifact) {
380 | this.primaryArtifact = primaryArtifact;
381 | }
382 |
383 | /**
384 | * @return {@link #attachClasses}
385 | */
386 | public boolean isAttachClasses() {
387 | return attachClasses;
388 | }
389 |
390 | /**
391 | * @param attachClasses {@link #attachClasses}
392 | */
393 | public void setAttachClasses(boolean attachClasses) {
394 | this.attachClasses = attachClasses;
395 | }
396 |
397 | /**
398 | * @return {@link #classesClassifier}
399 | */
400 | public String getClassesClassifier() {
401 | return classesClassifier;
402 | }
403 |
404 | /**
405 | * @param classesClassifier {@link #classesClassifier}
406 | */
407 | public void setClassesClassifier(String classesClassifier) {
408 | this.classesClassifier = classesClassifier;
409 | }
410 |
411 | /**
412 | * @return {@link #failOnMissingWebXml}
413 | */
414 | public boolean isFailOnMissingWebXml() {
415 | return failOnMissingWebXml;
416 | }
417 |
418 | /**
419 | * @param failOnMissingWebXml {@link #failOnMissingWebXml}
420 | */
421 | public void setFailOnMissingWebXml(boolean failOnMissingWebXml) {
422 | this.failOnMissingWebXml = failOnMissingWebXml;
423 | }
424 | }
425 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/WarProjectPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 |
25 | import org.apache.maven.model.Resource;
26 | import org.apache.maven.plugin.MojoExecutionException;
27 | import org.apache.maven.plugin.MojoFailureException;
28 | import cn.wanghaomiao.maven.plugin.seimi.Overlay;
29 | import cn.wanghaomiao.maven.plugin.seimi.util.PathSet;
30 | import org.apache.maven.shared.filtering.MavenFilteringException;
31 | import org.codehaus.plexus.util.DirectoryScanner;
32 | import org.codehaus.plexus.util.StringUtils;
33 |
34 | /**
35 | * Handles the project own resources, that is: The list of web resources, if any - The content of the
36 | * webapp directory if it exists
- The custom deployment descriptor(s), if any
- The content of the
37 | * classes directory if it exists
- The dependencies of the project
38 | *
39 | * @author Stephane Nicoll
40 | * @version $Id: WarProjectPackagingTask.java 1637197 2014-11-06 19:46:57Z khmarbaise $
41 | */
42 | public class WarProjectPackagingTask
43 | extends AbstractWarPackagingTask
44 | {
45 | private final Resource[] webResources;
46 |
47 | private final File webXml;
48 |
49 | private final File containerConfigXML;
50 |
51 | private final String id;
52 |
53 | private Overlay currentProjectOverlay;
54 |
55 | /**
56 | * @param webResources {@link #webResources}
57 | * @param webXml {@link #webXml}
58 | * @param containerConfigXml {@link #containerConfigXML}
59 | * @param currentProjectOverlay {@link #currentProjectOverlay}
60 | */
61 | public WarProjectPackagingTask( Resource[] webResources, File webXml, File containerConfigXml,
62 | Overlay currentProjectOverlay )
63 | {
64 | if ( webResources != null )
65 | {
66 | this.webResources = webResources;
67 | }
68 | else
69 | {
70 | this.webResources = new Resource[0];
71 | }
72 | this.webXml = webXml;
73 | this.containerConfigXML = containerConfigXml;
74 | this.currentProjectOverlay = currentProjectOverlay;
75 | this.id = currentProjectOverlay.getId();
76 | }
77 |
78 | /**
79 | * {@inheritDoc}
80 | */
81 | public void performPackaging( WarPackagingContext context )
82 | throws MojoExecutionException, MojoFailureException
83 | {
84 |
85 | context.getLog().info( "Processing war project" );
86 | // Prepare the INF directories
87 | File webinfDir = new File( context.getWebappDirectory(), WEB_INF_PATH );
88 | webinfDir.mkdirs();
89 | File metainfDir = new File( context.getWebappDirectory(), META_INF_PATH );
90 | metainfDir.mkdirs();
91 |
92 | handleWebResources( context );
93 |
94 | handeWebAppSourceDirectory( context );
95 |
96 | // Debug mode: dump the path set for the current build
97 | PathSet pathSet = context.getWebappStructure().getStructure( "currentBuild" );
98 | context.getLog().debug( "Dump of the current build pathSet content -->" );
99 | for ( String path : pathSet )
100 | {
101 | context.getLog().debug( path );
102 | }
103 | context.getLog().debug( "-- end of dump --" );
104 |
105 | handleDeploymentDescriptors( context, webinfDir, metainfDir );
106 |
107 | handleClassesDirectory( context );
108 |
109 | handleArtifacts( context );
110 | }
111 |
112 | /**
113 | * Handles the web resources.
114 | *
115 | * @param context the packaging context
116 | * @throws MojoExecutionException if a resource could not be copied
117 | */
118 | protected void handleWebResources( WarPackagingContext context )
119 | throws MojoExecutionException
120 | {
121 | for ( Resource resource : webResources )
122 | {
123 |
124 | // MWAR-246
125 | if ( resource.getDirectory() == null )
126 | {
127 | throw new MojoExecutionException( "The tag is missing from the tag." );
128 | }
129 |
130 | if ( !( new File( resource.getDirectory() ) ).isAbsolute() )
131 | {
132 | resource.setDirectory( context.getProject().getBasedir() + File.separator + resource.getDirectory() );
133 | }
134 |
135 | // Make sure that the resource directory is not the same as the webappDirectory
136 | if ( !resource.getDirectory().equals( context.getWebappDirectory().getPath() ) )
137 | {
138 |
139 | try
140 | {
141 | copyResources( context, resource );
142 | }
143 | catch ( IOException e )
144 | {
145 | throw new MojoExecutionException( "Could not copy resource [" + resource.getDirectory() + "]", e );
146 | }
147 | }
148 | }
149 | }
150 |
151 | /**
152 | * Handles the webapp sources.
153 | *
154 | * @param context the packaging context
155 | * @throws MojoExecutionException if the sources could not be copied
156 | */
157 | protected void handeWebAppSourceDirectory( WarPackagingContext context )
158 | throws MojoExecutionException
159 | {
160 | // CHECKSTYLE_OFF: LineLength
161 | if ( !context.getWebappSourceDirectory().exists() )
162 | {
163 | context.getLog().debug( "webapp sources directory does not exist - skipping." );
164 | }
165 | else if ( !context.getWebappSourceDirectory().getAbsolutePath().equals( context.getWebappDirectory().getPath() ) )
166 | {
167 | context.getLog().info( "Copying webapp resources [" + context.getWebappSourceDirectory() + "]" );
168 | final PathSet sources =
169 | getFilesToIncludes( context.getWebappSourceDirectory(), context.getWebappSourceIncludes(),
170 | context.getWebappSourceExcludes(), context.isWebappSourceIncludeEmptyDirectories() );
171 |
172 | try
173 | {
174 | copyFiles( id, context, context.getWebappSourceDirectory(), sources, false );
175 | }
176 | catch ( IOException e )
177 | {
178 | throw new MojoExecutionException( "Could not copy webapp sources ["
179 | + context.getWebappDirectory().getAbsolutePath() + "]", e );
180 | }
181 | }
182 | // CHECKSTYLE_ON: LineLength
183 | }
184 |
185 | /**
186 | * Handles the webapp artifacts.
187 | *
188 | * @param context the packaging context
189 | * @throws MojoExecutionException if the artifacts could not be packaged
190 | */
191 | protected void handleArtifacts( WarPackagingContext context )
192 | throws MojoExecutionException
193 | {
194 | @SuppressWarnings( "unchecked" )
195 | ArtifactsPackagingTask task =
196 | new ArtifactsPackagingTask( context.getProject().getArtifacts(), currentProjectOverlay );
197 | task.performPackaging( context );
198 | }
199 |
200 | /**
201 | * Handles the webapp classes.
202 | *
203 | * @param context the packaging context
204 | * @throws MojoExecutionException if the classes could not be packaged
205 | */
206 | protected void handleClassesDirectory( WarPackagingContext context )
207 | throws MojoExecutionException
208 | {
209 | ClassesPackagingTask task = new ClassesPackagingTask( currentProjectOverlay );
210 | task.performPackaging( context );
211 | }
212 |
213 | /**
214 | * Handles the deployment descriptors, if specified. Note that the behavior here is slightly different since the
215 | * customized entry always win, even if an overlay has already packaged a web.xml previously.
216 | *
217 | * @param context the packaging context
218 | * @param webinfDir the web-inf directory
219 | * @param metainfDir the meta-inf directory
220 | * @throws MojoFailureException if the web.xml is specified but does not exist
221 | * @throws MojoExecutionException if an error occurred while copying the descriptors
222 | */
223 | protected void handleDeploymentDescriptors( WarPackagingContext context, File webinfDir, File metainfDir )
224 | throws MojoFailureException, MojoExecutionException
225 | {
226 | try
227 | {
228 | if ( webXml != null && StringUtils.isNotEmpty( webXml.getName() ) )
229 | {
230 | if ( !webXml.exists() )
231 | {
232 | throw new MojoFailureException( "The specified web.xml file '" + webXml + "' does not exist" );
233 | }
234 |
235 | // Making sure that it won't get overlayed
236 | context.getWebappStructure().registerFileForced( id, WEB_INF_PATH + "/web.xml" );
237 |
238 | if ( context.isFilteringDeploymentDescriptors() )
239 | {
240 | context.getMavenFileFilter().copyFile( webXml, new File( webinfDir, "web.xml" ), true,
241 | context.getFilterWrappers(), getEncoding( webXml ) );
242 | }
243 | else
244 | {
245 | copyFile( context, webXml, new File( webinfDir, "web.xml" ), "WEB-INF/web.xml", true );
246 | }
247 | }
248 | else
249 | {
250 | // the webXml can be the default one
251 | File defaultWebXml = new File( context.getWebappSourceDirectory(), WEB_INF_PATH + "/web.xml" );
252 | // if exists we can filter it
253 | if ( defaultWebXml.exists() && context.isFilteringDeploymentDescriptors() )
254 | {
255 | context.getWebappStructure().registerFile( id, WEB_INF_PATH + "/web.xml" );
256 | context.getMavenFileFilter().copyFile( defaultWebXml, new File( webinfDir, "web.xml" ), true,
257 | context.getFilterWrappers(), getEncoding( defaultWebXml ) );
258 | }
259 | }
260 |
261 | if ( containerConfigXML != null && StringUtils.isNotEmpty( containerConfigXML.getName() ) )
262 | {
263 | String xmlFileName = containerConfigXML.getName();
264 |
265 | context.getWebappStructure().registerFileForced( id, META_INF_PATH + "/" + xmlFileName );
266 |
267 | if ( context.isFilteringDeploymentDescriptors() )
268 | {
269 | context.getMavenFileFilter().copyFile( containerConfigXML, new File( metainfDir, xmlFileName ),
270 | true, context.getFilterWrappers(),
271 | getEncoding( containerConfigXML ) );
272 | }
273 | else
274 | {
275 | copyFile( context, containerConfigXML, new File( metainfDir, xmlFileName ), "META-INF/"
276 | + xmlFileName, true );
277 | }
278 | }
279 | }
280 | catch ( IOException e )
281 | {
282 | throw new MojoExecutionException( "Failed to copy deployment descriptor", e );
283 | }
284 | catch ( MavenFilteringException e )
285 | {
286 | throw new MojoExecutionException( "Failed to copy deployment descriptor", e );
287 | }
288 | }
289 |
290 | /**
291 | * Copies webapp webResources from the specified directory.
292 | *
293 | * @param context the WAR packaging context to use
294 | * @param resource the resource to copy
295 | * @throws IOException if an error occurred while copying the resources
296 | * @throws MojoExecutionException if an error occurred while retrieving the filter properties
297 | */
298 | public void copyResources( WarPackagingContext context, Resource resource )
299 | throws IOException, MojoExecutionException
300 | {
301 | if ( !context.getWebappDirectory().exists() )
302 | {
303 | context.getLog().warn( "Not copying webapp webResources [" + resource.getDirectory()
304 | + "]: webapp directory [" + context.getWebappDirectory().getAbsolutePath()
305 | + "] does not exist!" );
306 | }
307 |
308 | context.getLog().info( "Copying webapp webResources [" + resource.getDirectory() + "] to ["
309 | + context.getWebappDirectory().getAbsolutePath() + "]" );
310 | String[] fileNames = getFilesToCopy( resource );
311 | for ( String fileName : fileNames )
312 | {
313 | String targetFileName = fileName;
314 | if ( resource.getTargetPath() != null )
315 | {
316 | // TODO make sure this thing is 100% safe
317 | // MWAR-129 if targetPath is only a dot . or ./
318 | // and the Resource is in a part of the warSourceDirectory the file from sources will override this
319 | // that's we don't have to add the targetPath yep not nice but works
320 | if ( !StringUtils.equals( ".", resource.getTargetPath() )
321 | && !StringUtils.equals( "./", resource.getTargetPath() ) )
322 | {
323 | targetFileName = resource.getTargetPath() + File.separator + targetFileName;
324 | }
325 | }
326 | if ( resource.isFiltering() && !context.isNonFilteredExtension( fileName ) )
327 | {
328 | copyFilteredFile( id, context, new File( resource.getDirectory(), fileName ), targetFileName );
329 | }
330 | else
331 | {
332 | copyFile( id, context, new File( resource.getDirectory(), fileName ), targetFileName );
333 | }
334 | }
335 | }
336 |
337 | /**
338 | * Returns a list of filenames that should be copied over to the destination directory.
339 | *
340 | * @param resource the resource to be scanned
341 | * @return the array of filenames, relative to the sourceDir
342 | */
343 | private String[] getFilesToCopy( Resource resource )
344 | {
345 | // CHECKSTYLE_OFF: LineLength
346 | DirectoryScanner scanner = new DirectoryScanner();
347 | scanner.setBasedir( resource.getDirectory() );
348 | if ( resource.getIncludes() != null && !resource.getIncludes().isEmpty() )
349 | {
350 | scanner.setIncludes( (String[]) resource.getIncludes().toArray( new String[resource.getIncludes().size()] ) );
351 | }
352 | else
353 | {
354 | scanner.setIncludes( DEFAULT_INCLUDES );
355 | }
356 | if ( resource.getExcludes() != null && !resource.getExcludes().isEmpty() )
357 | {
358 | scanner.setExcludes( (String[]) resource.getExcludes().toArray( new String[resource.getExcludes().size()] ) );
359 | }
360 |
361 | scanner.addDefaultExcludes();
362 |
363 | scanner.scan();
364 |
365 | return scanner.getIncludedFiles();
366 | // CHECKSTYLE_ON: LineLength
367 | }
368 | }
369 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/packaging/AbstractWarPackagingTask.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.packaging;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 |
25 | import cn.wanghaomiao.maven.plugin.seimi.util.PathSet;
26 | import org.apache.commons.io.input.XmlStreamReader;
27 | import org.apache.maven.artifact.Artifact;
28 | import org.apache.maven.plugin.MojoExecutionException;
29 | import cn.wanghaomiao.maven.plugin.seimi.util.WebappStructure;
30 | import org.apache.maven.shared.filtering.MavenFilteringException;
31 | import org.apache.maven.shared.mapping.MappingUtils;
32 | import org.codehaus.plexus.archiver.ArchiverException;
33 | import org.codehaus.plexus.archiver.UnArchiver;
34 | import org.codehaus.plexus.archiver.jar.JarArchiver;
35 | import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
36 | import org.codehaus.plexus.interpolation.InterpolationException;
37 | import org.codehaus.plexus.util.DirectoryScanner;
38 | import org.codehaus.plexus.util.FileUtils;
39 | import org.codehaus.plexus.util.IOUtil;
40 |
41 | /**
42 | * @author Stephane Nicoll
43 | * @version $Id: AbstractWarPackagingTask.java 1637197 2014-11-06 19:46:57Z khmarbaise $
44 | */
45 | public abstract class AbstractWarPackagingTask
46 | implements WarPackagingTask
47 | {
48 | /**
49 | * The default list of includes.
50 | */
51 | public static final String[] DEFAULT_INCLUDES = { "**/**" };
52 |
53 | /**
54 | * The {@code WEB-INF} path.
55 | */
56 | public static final String WEB_INF_PATH = "seimi";
57 |
58 | /**
59 | * The {@code META-INF} path.
60 | */
61 | public static final String META_INF_PATH = "seimi";
62 |
63 | /**
64 | * The {@code classes} path.
65 | */
66 | public static final String CLASSES_PATH = "seimi/classes/";
67 |
68 | /**
69 | * The {@code lib} path.
70 | */
71 | public static final String LIB_PATH = "seimi/lib/";
72 |
73 | /**
74 | * Copies the files if possible with an optional target prefix.
75 | *
76 | * Copy uses a first-win strategy: files that have already been copied by previous tasks are ignored. This method
77 | * makes sure to update the list of protected files which gives the list of files that have already been copied.
78 | *
79 | * If the structure of the source directory is not the same as the root of the webapp, use the targetPrefix
80 | * parameter to specify in which particular directory the files should be copied. Use null to copy the
81 | * files with the same structure
82 | *
83 | * @param sourceId the source id
84 | * @param context the context to use
85 | * @param sourceBaseDir the base directory from which the sourceFilesSet will be copied
86 | * @param sourceFilesSet the files to be copied
87 | * @param targetPrefix the prefix to add to the target file name
88 | * @param filtered filter or not.
89 | * @throws IOException if an error occurred while copying the files
90 | * @throws MojoExecutionException if an error occurs.
91 | */
92 | protected void copyFiles( String sourceId, WarPackagingContext context, File sourceBaseDir, PathSet sourceFilesSet,
93 | String targetPrefix, boolean filtered )
94 | throws IOException, MojoExecutionException
95 | {
96 | for ( String fileToCopyName : sourceFilesSet.paths() )
97 | {
98 | final File sourceFile = new File( sourceBaseDir, fileToCopyName );
99 |
100 | String destinationFileName;
101 | if ( targetPrefix == null )
102 | {
103 | destinationFileName = fileToCopyName;
104 | }
105 | else
106 | {
107 | destinationFileName = targetPrefix + fileToCopyName;
108 | }
109 |
110 | if ( filtered && !context.isNonFilteredExtension( sourceFile.getName() ) )
111 | {
112 | copyFilteredFile( sourceId, context, sourceFile, destinationFileName );
113 | }
114 | else
115 | {
116 | copyFile( sourceId, context, sourceFile, destinationFileName );
117 | }
118 | }
119 | }
120 |
121 | /**
122 | * Copies the files if possible as is.
123 | *
124 | * Copy uses a first-win strategy: files that have already been copied by previous tasks are ignored. This method
125 | * makes sure to update the list of protected files which gives the list of files that have already been copied.
126 | *
127 | * @param sourceId the source id
128 | * @param context the context to use
129 | * @param sourceBaseDir the base directory from which the sourceFilesSet will be copied
130 | * @param sourceFilesSet the files to be copied
131 | * @param filtered filter or not.
132 | * @throws IOException if an error occurred while copying the files
133 | * @throws MojoExecutionException break the build.
134 | */
135 | protected void copyFiles( String sourceId, WarPackagingContext context, File sourceBaseDir, PathSet sourceFilesSet,
136 | boolean filtered )
137 | throws IOException, MojoExecutionException
138 | {
139 | copyFiles( sourceId, context, sourceBaseDir, sourceFilesSet, null, filtered );
140 | }
141 |
142 | /**
143 | * Copy the specified file if the target location has not yet already been used.
144 | *
145 | * The targetFileName is the relative path according to the root of the generated web application.
146 | *
147 | * @param sourceId the source id
148 | * @param context the context to use
149 | * @param file the file to copy
150 | * @param targetFilename the relative path according to the root of the webapp
151 | * @throws IOException if an error occurred while copying
152 | */
153 | // CHECKSTYLE_OFF: LineLength
154 | protected void copyFile( String sourceId, final WarPackagingContext context, final File file, String targetFilename )
155 | throws IOException
156 | // CHECKSTYLE_ON: LineLength
157 | {
158 | final File targetFile = new File( context.getWebappDirectory(), targetFilename );
159 |
160 | if ( file.isFile() )
161 | {
162 | context.getWebappStructure().registerFile( sourceId, targetFilename,
163 | new WebappStructure.RegistrationCallback()
164 | {
165 | public void registered( String ownerId, String targetFilename )
166 | throws IOException
167 | {
168 | copyFile( context, file, targetFile, targetFilename,
169 | false );
170 | }
171 |
172 | public void alreadyRegistered( String ownerId,
173 | String targetFilename )
174 | throws IOException
175 | {
176 | copyFile( context, file, targetFile, targetFilename,
177 | true );
178 | }
179 |
180 | public void refused( String ownerId, String targetFilename,
181 | String actualOwnerId )
182 | throws IOException
183 | {
184 | context.getLog().debug( " - "
185 | + targetFilename
186 | + " wasn't copied because it has "
187 | + "already been packaged for overlay ["
188 | + actualOwnerId + "]." );
189 | }
190 |
191 | public void superseded( String ownerId,
192 | String targetFilename,
193 | String deprecatedOwnerId )
194 | throws IOException
195 | {
196 | context.getLog().info( "File ["
197 | + targetFilename
198 | + "] belonged to overlay ["
199 | + deprecatedOwnerId
200 | + "] so it will be overwritten." );
201 | copyFile( context, file, targetFile, targetFilename,
202 | false );
203 | }
204 |
205 | public void supersededUnknownOwner( String ownerId,
206 | String targetFilename,
207 | String unknownOwnerId )
208 | throws IOException
209 | {
210 | // CHECKSTYLE_OFF: LineLength
211 | context.getLog().warn( "File ["
212 | + targetFilename
213 | + "] belonged to overlay ["
214 | + unknownOwnerId
215 | + "] which does not exist anymore in the current project. It is recommended to invoke "
216 | + "clean if the dependencies of the project changed." );
217 | // CHECKSTYLE_ON: LineLength
218 | copyFile( context, file, targetFile, targetFilename,
219 | false );
220 | }
221 | } );
222 | }
223 | else if ( !targetFile.exists() && !targetFile.mkdirs() )
224 | {
225 | context.getLog().info( "Failed to create directory " + targetFile.getAbsolutePath() );
226 | }
227 | }
228 |
229 | /**
230 | * Copy the specified file if the target location has not yet already been used and filter its content with the
231 | * configured filter properties.
232 | *
233 | * The targetFileName is the relative path according to the root of the generated web application.
234 | *
235 | * @param sourceId the source id
236 | * @param context the context to use
237 | * @param file the file to copy
238 | * @param targetFilename the relative path according to the root of the webapp
239 | * @return true if the file has been copied, false otherwise
240 | * @throws IOException if an error occurred while copying
241 | * @throws MojoExecutionException if an error occurred while retrieving the filter properties
242 | */
243 | protected boolean copyFilteredFile( String sourceId, final WarPackagingContext context, File file,
244 | String targetFilename )
245 | throws IOException, MojoExecutionException
246 | {
247 |
248 | if ( context.getWebappStructure().registerFile( sourceId, targetFilename ) )
249 | {
250 | final File targetFile = new File( context.getWebappDirectory(), targetFilename );
251 | final String encoding;
252 | try
253 | {
254 | if ( isXmlFile( file ) )
255 | {
256 | // For xml-files we extract the encoding from the files
257 | encoding = getEncoding( file );
258 | }
259 | else
260 | {
261 | // For all others we use the configured encoding
262 | encoding = context.getResourceEncoding();
263 | }
264 | // fix for MWAR-36, ensures that the parent dir are created first
265 | targetFile.getParentFile().mkdirs();
266 |
267 | context.getMavenFileFilter().copyFile( file, targetFile, true, context.getFilterWrappers(), encoding );
268 | }
269 | catch ( MavenFilteringException e )
270 | {
271 | throw new MojoExecutionException( e.getMessage(), e );
272 | }
273 | // CHECKSTYLE_OFF: LineLength
274 | // Add the file to the protected list
275 | context.getLog().debug( " + " + targetFilename + " has been copied (filtered encoding='" + encoding + "')." );
276 | // CHECKSTYLE_ON: LineLength
277 | return true;
278 | }
279 | else
280 | {
281 | context.getLog().debug( " - " + targetFilename
282 | + " wasn't copied because it has already been packaged (filtered)." );
283 | return false;
284 | }
285 | }
286 |
287 | /**
288 | * Unpacks the specified file to the specified directory.
289 | *
290 | * @param context the packaging context
291 | * @param file the file to unpack
292 | * @param unpackDirectory the directory to use for th unpacked file
293 | * @throws MojoExecutionException if an error occurred while unpacking the file
294 | */
295 | protected void doUnpack( WarPackagingContext context, File file, File unpackDirectory )
296 | throws MojoExecutionException
297 | {
298 | String archiveExt = FileUtils.getExtension( file.getAbsolutePath() ).toLowerCase();
299 |
300 | try
301 | {
302 | UnArchiver unArchiver = context.getArchiverManager().getUnArchiver( archiveExt );
303 | unArchiver.setSourceFile( file );
304 | unArchiver.setUseJvmChmod( context.isUseJvmChmod() );
305 | unArchiver.setDestDirectory( unpackDirectory );
306 | unArchiver.setOverwrite( true );
307 | unArchiver.extract();
308 | }
309 | catch ( ArchiverException e )
310 | {
311 | throw new MojoExecutionException( "Error unpacking file [" + file.getAbsolutePath() + "]" + "to ["
312 | + unpackDirectory.getAbsolutePath() + "]", e );
313 | }
314 | catch ( NoSuchArchiverException e )
315 | {
316 | context.getLog().warn( "Skip unpacking dependency file [" + file.getAbsolutePath()
317 | + " with unknown extension [" + archiveExt + "]" );
318 | }
319 | }
320 |
321 | /**
322 | * Copy file from source to destination. The directories up to destination will be created if they
323 | * don't already exist. if the onlyIfModified flag is false, destination will be
324 | * overwritten if it already exists. If the flag is true destination will be overwritten if it's not up to
325 | * date.
326 | *
327 | *
328 | * @param context the packaging context
329 | * @param source an existing non-directory File to copy bytes from
330 | * @param destination a non-directory File to write bytes to (possibly overwriting).
331 | * @param targetFilename the relative path of the file from the webapp root directory
332 | * @param onlyIfModified if true, copy the file only if the source has changed, always copy otherwise
333 | * @return true if the file has been copied/updated, false otherwise
334 | * @throws IOException if source does not exist, destination cannot be written to, or an
335 | * IO error occurs during copying
336 | */
337 | protected boolean copyFile( WarPackagingContext context, File source, File destination, String targetFilename,
338 | boolean onlyIfModified )
339 | throws IOException
340 | {
341 | if ( onlyIfModified && destination.lastModified() >= source.lastModified() )
342 | {
343 | context.getLog().debug( " * " + targetFilename + " is up to date." );
344 | return false;
345 | }
346 | else
347 | {
348 | if ( source.isDirectory() )
349 | {
350 | context.getLog().warn( " + " + targetFilename + " is packaged from the source folder" );
351 |
352 | try
353 | {
354 | JarArchiver archiver = context.getJarArchiver();
355 | archiver.addDirectory( source );
356 | archiver.setDestFile( destination );
357 | archiver.createArchive();
358 | }
359 | catch ( ArchiverException e )
360 | {
361 | String msg = "Failed to create " + targetFilename;
362 | context.getLog().error( msg, e );
363 | IOException ioe = new IOException( msg );
364 | ioe.initCause( e );
365 | throw ioe;
366 | }
367 | }
368 | else
369 | {
370 | FileUtils.copyFile( source.getCanonicalFile(), destination );
371 | // preserve timestamp
372 | destination.setLastModified( source.lastModified() );
373 | context.getLog().debug( " + " + targetFilename + " has been copied." );
374 | }
375 | return true;
376 | }
377 | }
378 |
379 | /**
380 | * Get the encoding from an XML-file.
381 | *
382 | * @param webXml the XML-file
383 | * @return The encoding of the XML-file, or UTF-8 if it's not specified in the file
384 | * @throws java.io.IOException if an error occurred while reading the file
385 | */
386 | protected String getEncoding( File webXml )
387 | throws IOException
388 | {
389 | XmlStreamReader xmlReader = new XmlStreamReader( webXml );
390 | try
391 | {
392 | return xmlReader.getEncoding();
393 | }
394 | finally
395 | {
396 | IOUtil.close( xmlReader );
397 | }
398 | }
399 |
400 | /**
401 | * Returns the file to copy. If the includes are null or empty, the default includes are used.
402 | *
403 | * @param baseDir the base directory to start from
404 | * @param includes the includes
405 | * @param excludes the excludes
406 | * @return the files to copy
407 | */
408 | protected PathSet getFilesToIncludes( File baseDir, String[] includes, String[] excludes )
409 | {
410 | return getFilesToIncludes( baseDir, includes, excludes, false );
411 | }
412 |
413 | /**
414 | * Returns the file to copy. If the includes are null or empty, the default includes are used.
415 | *
416 | * @param baseDir the base directory to start from
417 | * @param includes the includes
418 | * @param excludes the excludes
419 | * @param includeDirectories include directories yes or not.
420 | * @return the files to copy
421 | */
422 | // CHECKSTYLE_OFF: LineLength
423 | protected PathSet getFilesToIncludes( File baseDir, String[] includes, String[] excludes, boolean includeDirectories )
424 | // CHECKSTYLE_ON: LineLength
425 | {
426 | final DirectoryScanner scanner = new DirectoryScanner();
427 | scanner.setBasedir( baseDir );
428 |
429 | if ( excludes != null )
430 | {
431 | scanner.setExcludes( excludes );
432 | }
433 | scanner.addDefaultExcludes();
434 |
435 | if ( includes != null && includes.length > 0 )
436 | {
437 | scanner.setIncludes( includes );
438 | }
439 | else
440 | {
441 | scanner.setIncludes( DEFAULT_INCLUDES );
442 | }
443 |
444 | scanner.scan();
445 |
446 | PathSet pathSet = new PathSet( scanner.getIncludedFiles() );
447 |
448 | if ( includeDirectories )
449 | {
450 | pathSet.addAll( scanner.getIncludedDirectories() );
451 | }
452 |
453 | return pathSet;
454 | }
455 |
456 | /**
457 | * Returns the final name of the specified artifact.
458 | *
459 | * If the outputFileNameMapping is set, it is used, otherwise the standard naming scheme is used.
460 | *
461 | * @param context the packaging context
462 | * @param artifact the artifact
463 | * @return the converted filename of the artifact
464 | * @throws InterpolationException in case of interpolation problem.
465 | */
466 | protected String getArtifactFinalName( WarPackagingContext context, Artifact artifact )
467 | throws InterpolationException
468 | {
469 | if ( context.getOutputFileNameMapping() != null )
470 | {
471 | return MappingUtils.evaluateFileNameMapping( context.getOutputFileNameMapping(), artifact );
472 | }
473 |
474 | String classifier = artifact.getClassifier();
475 | if ( ( classifier != null ) && !( "".equals( classifier.trim() ) ) )
476 | {
477 | return MappingUtils.evaluateFileNameMapping( MappingUtils.DEFAULT_FILE_NAME_MAPPING_CLASSIFIER, artifact );
478 | }
479 | else
480 | {
481 | return MappingUtils.evaluateFileNameMapping( MappingUtils.DEFAULT_FILE_NAME_MAPPING, artifact );
482 | }
483 |
484 | }
485 |
486 | /**
487 | * Returns true if the File-object is a file (not a directory) that is not
488 | * null and has a file name that ends in ".xml".
489 | *
490 | * @param file The file to check
491 | * @return true if the file is an xml-file, otherwise false
492 | * @since 2.3
493 | */
494 | private boolean isXmlFile( File file )
495 | {
496 | return file != null && file.isFile() && file.getName().endsWith( ".xml" );
497 | }
498 | }
499 |
--------------------------------------------------------------------------------
/src/main/java/cn/wanghaomiao/maven/plugin/seimi/util/WebappStructure.java:
--------------------------------------------------------------------------------
1 | package cn.wanghaomiao.maven.plugin.seimi.util;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | */
21 |
22 | import org.apache.maven.artifact.Artifact;
23 | import org.apache.maven.model.Dependency;
24 | import org.codehaus.plexus.util.StringUtils;
25 |
26 | import java.io.IOException;
27 | import java.util.ArrayList;
28 | import java.util.Collections;
29 | import java.util.HashMap;
30 | import java.util.Iterator;
31 | import java.util.List;
32 | import java.util.Map;
33 | import java.util.Set;
34 |
35 | /**
36 | * Represents the structure of a web application composed of multiple overlays. Each overlay is registered within this
37 | * structure with the set of files it holds.
38 | *
39 | * Note that this structure is persisted to disk at each invocation to store which owner holds which path (file).
40 | *
41 | * @author Stephane Nicoll
42 | * @version $Id: WebappStructure.java 1636820 2014-11-05 08:27:25Z khmarbaise $
43 | */
44 | public class WebappStructure
45 | {
46 |
47 | private Map registeredFiles;
48 |
49 | private List dependenciesInfo;
50 |
51 | private transient PathSet allFiles = new PathSet();
52 |
53 | private transient WebappStructure cache;
54 |
55 | /**
56 | * Creates a new empty instance.
57 | *
58 | * @param dependencies the dependencies of the project
59 | */
60 | public WebappStructure( List dependencies )
61 | {
62 | this.dependenciesInfo = createDependenciesInfoList( dependencies );
63 | this.registeredFiles = new HashMap();
64 | this.cache = null;
65 | }
66 |
67 | /**
68 | * Creates a new instance with the specified cache.
69 | *
70 | * @param dependencies the dependencies of the project
71 | * @param cache the cache
72 | */
73 | public WebappStructure( List dependencies, WebappStructure cache )
74 | {
75 | this.dependenciesInfo = createDependenciesInfoList( dependencies );
76 | this.registeredFiles = new HashMap();
77 | if ( cache == null )
78 | {
79 | this.cache = new WebappStructure( dependencies );
80 | }
81 | else
82 | {
83 | this.cache = cache;
84 | }
85 | }
86 |
87 | /**
88 | * Returns the list of {@link DependencyInfo} for the project.
89 | *
90 | * @return the dependencies information of the project
91 | */
92 | public List getDependenciesInfo()
93 | {
94 | return dependenciesInfo;
95 | }
96 |
97 | /**
98 | * Returns the dependencies of the project.
99 | *
100 | * @return the dependencies of the project
101 | */
102 | public List getDependencies()
103 | {
104 | final List result = new ArrayList();
105 | if ( dependenciesInfo == null )
106 | {
107 | return result;
108 | }
109 | for ( DependencyInfo dependencyInfo : dependenciesInfo )
110 | {
111 | result.add( dependencyInfo.getDependency() );
112 | }
113 | return result;
114 | }
115 |
116 | /**
117 | * Specify if the specified path is registered or not.
118 | *
119 | * @param path the relative path from the webapp root directory
120 | * @return true if the path is registered, false otherwise
121 | */
122 | public boolean isRegistered( String path )
123 | {
124 | return getFullStructure().contains( path );
125 |
126 | }
127 |
128 | /**
129 | * Registers the specified path for the specified owner. Returns true if the path is not already
130 | * registered, false otherwise.
131 | *
132 | * @param id the owner of the path
133 | * @param path the relative path from the webapp root directory
134 | * @return true if the file was registered successfully
135 | */
136 | public boolean registerFile( String id, String path )
137 | {
138 | if ( !isRegistered( path ) )
139 | {
140 | doRegister( id, path );
141 | return true;
142 | }
143 | else
144 | {
145 | return false;
146 | }
147 | }
148 |
149 | /**
150 | * Forces the registration of the specified path for the specified owner. If the file is not registered yet, a
151 | * simple registration is performed. If the file already exists, the owner changes to the specified one.
152 | *
153 | * Beware that the semantic of the return boolean is different than the one from
154 | * {@link #registerFile(String, String)}; returns true if an owner replacement was made and false
155 | * if the file was simply registered for the first time.
156 | *
157 | * @param id the owner of the path
158 | * @param path the relative path from the webapp root directory
159 | * @return false if the file did not exist, true if the owner was replaced
160 | */
161 | public boolean registerFileForced( String id, String path )
162 | {
163 | if ( !isRegistered( path ) )
164 | {
165 | doRegister( id, path );
166 | return false;
167 | }
168 | else
169 | {
170 | // Force the switch to the new owner
171 | getStructure( getOwner( path ) ).remove( path );
172 | getStructure( id ).add( path );
173 | return true;
174 | }
175 |
176 | }
177 |
178 | /**
179 | * Registers the specified path for the specified owner. Invokes the callback with the result of the
180 | * registration.
181 | *
182 | * @param id the owner of the path
183 | * @param path the relative path from the webapp root directory
184 | * @param callback the callback to invoke with the result of the registration
185 | * @throws IOException if the callback invocation throws an IOException
186 | */
187 | public void registerFile( String id, String path, RegistrationCallback callback )
188 | throws IOException
189 | {
190 |
191 | // If the file is already in the current structure, rejects it with the current owner
192 | if ( isRegistered( path ) )
193 | {
194 | callback.refused( id, path, getOwner( path ) );
195 | }
196 | else
197 | {
198 | doRegister( id, path );
199 | // This is a new file
200 | if ( cache.getOwner( path ) == null )
201 | {
202 | callback.registered( id, path );
203 |
204 | } // The file already belonged to this owner
205 | else if ( cache.getOwner( path ).equals( id ) )
206 | {
207 | callback.alreadyRegistered( id, path );
208 | } // The file belongs to another owner and it's known currently
209 | else if ( getOwners().contains( cache.getOwner( path ) ) )
210 | {
211 | callback.superseded( id, path, cache.getOwner( path ) );
212 | } // The file belongs to another owner and it's unknown
213 | else
214 | {
215 | callback.supersededUnknownOwner( id, path, cache.getOwner( path ) );
216 | }
217 | }
218 | }
219 |
220 | /**
221 | * Returns the owner of the specified path. If the file is not registered, returns null
222 | *
223 | * @param path the relative path from the webapp root directory
224 | * @return the owner or null.
225 | */
226 | public String getOwner( String path )
227 | {
228 | if ( !isRegistered( path ) )
229 | {
230 | return null;
231 | }
232 | else
233 | {
234 | for ( final String owner : registeredFiles.keySet() )
235 | {
236 | final PathSet structure = getStructure( owner );
237 | if ( structure.contains( path ) )
238 | {
239 | return owner;
240 | }
241 |
242 | }
243 | throw new IllegalStateException( "Should not happen, path [" + path
244 | + "] is flagged as being registered but was not found." );
245 | }
246 |
247 | }
248 |
249 | /**
250 | * Returns the owners. Note that this the returned {@link Set} may be inconsistent since it represents a persistent
251 | * cache across multiple invocations.
252 | *
253 | * For instance, if an overlay was removed in this execution, it will be still be there till the cache is cleaned.
254 | * This happens when the clean mojo is invoked.
255 | *
256 | * @return the list of owners
257 | */
258 | public Set getOwners()
259 | {
260 | return registeredFiles.keySet();
261 | }
262 |
263 | /**
264 | * Returns all paths that have been registered so far.
265 | *
266 | * @return all registered path
267 | */
268 | public PathSet getFullStructure()
269 | {
270 | return allFiles;
271 | }
272 |
273 | /**
274 | * Returns the list of registered files for the specified owner.
275 | *
276 | * @param id the owner
277 | * @return the list of files registered for that owner
278 | */
279 | public PathSet getStructure( String id )
280 | {
281 | PathSet pathSet = registeredFiles.get( id );
282 | if ( pathSet == null )
283 | {
284 | pathSet = new PathSet();
285 | registeredFiles.put( id, pathSet );
286 | }
287 | return pathSet;
288 | }
289 |
290 | /**
291 | * Analyze the dependencies of the project using the specified callback.
292 | *
293 | * @param callback the callback to use to report the result of the analysis
294 | */
295 | public void analyseDependencies( DependenciesAnalysisCallback callback )
296 | {
297 | if ( callback == null )
298 | {
299 | throw new NullPointerException( "Callback could not be null." );
300 | }
301 | if ( cache == null )
302 | {
303 | // Could not analyze dependencies without a cache
304 | return;
305 | }
306 |
307 | final List currentDependencies = new ArrayList( getDependencies() );
308 | final List previousDependencies = new ArrayList( cache.getDependencies() );
309 | final Iterator it = currentDependencies.listIterator();
310 | while ( it.hasNext() )
311 | {
312 | Dependency dependency = it.next();
313 | // Check if the dependency is there "as is"
314 |
315 | final Dependency matchingDependency = matchDependency( previousDependencies, dependency );
316 | if ( matchingDependency != null )
317 | {
318 | callback.unchangedDependency( dependency );
319 | // Handled so let's remove
320 | it.remove();
321 | previousDependencies.remove( matchingDependency );
322 | }
323 | else
324 | {
325 | // Try to get the dependency
326 | final Dependency previousDep = findDependency( dependency, previousDependencies );
327 | if ( previousDep == null )
328 | {
329 | callback.newDependency( dependency );
330 | it.remove();
331 | }
332 | else if ( !dependency.getVersion().equals( previousDep.getVersion() ) )
333 | {
334 | callback.updatedVersion( dependency, previousDep.getVersion() );
335 | it.remove();
336 | previousDependencies.remove( previousDep );
337 | }
338 | else if ( !dependency.getScope().equals( previousDep.getScope() ) )
339 | {
340 | callback.updatedScope( dependency, previousDep.getScope() );
341 | it.remove();
342 | previousDependencies.remove( previousDep );
343 | }
344 | else if ( dependency.isOptional() != previousDep.isOptional() )
345 | {
346 | callback.updatedOptionalFlag( dependency, previousDep.isOptional() );
347 | it.remove();
348 | previousDependencies.remove( previousDep );
349 | }
350 | else
351 | {
352 | callback.updatedUnknown( dependency, previousDep );
353 | it.remove();
354 | previousDependencies.remove( previousDep );
355 | }
356 | }
357 | }
358 | for ( Dependency dependency : previousDependencies )
359 | {
360 | callback.removedDependency( dependency );
361 | }
362 | }
363 |
364 | /**
365 | * Registers the target file name for the specified artifact.
366 | *
367 | * @param artifact the artifact
368 | * @param targetFileName the target file name
369 | */
370 | public void registerTargetFileName( Artifact artifact, String targetFileName )
371 | {
372 | if ( dependenciesInfo != null )
373 | {
374 | for ( DependencyInfo dependencyInfo : dependenciesInfo )
375 | {
376 | if ( WarUtils.isRelated( artifact, dependencyInfo.getDependency() ) )
377 | {
378 | dependencyInfo.setTargetFileName( targetFileName );
379 | }
380 | }
381 | }
382 | }
383 |
384 | /**
385 | * Returns the cached target file name that matches the specified dependency, that is the target file name of the
386 | * previous run.
387 | *
388 | * The dependency object may have changed so the comparison is based on basic attributes of the dependency.
389 | *
390 | * @param dependency a dependency
391 | * @return the target file name of the last run for this dependency
392 | */
393 | public String getCachedTargetFileName( Dependency dependency )
394 | {
395 | if ( cache == null )
396 | {
397 | return null;
398 | }
399 | for ( DependencyInfo dependencyInfo : cache.getDependenciesInfo() )
400 | {
401 | final Dependency dependency2 = dependencyInfo.getDependency();
402 | if ( StringUtils.equals( dependency.getGroupId(), dependency2.getGroupId() )
403 | && StringUtils.equals( dependency.getArtifactId(), dependency2.getArtifactId() )
404 | && StringUtils.equals( dependency.getType(), dependency2.getType() )
405 | && StringUtils.equals( dependency.getClassifier(), dependency2.getClassifier() ) )
406 | {
407 |
408 | return dependencyInfo.getTargetFileName();
409 |
410 | }
411 | }
412 | return null;
413 | }
414 |
415 | // Private helpers
416 |
417 | private void doRegister( String id, String path )
418 | {
419 | getFullStructure().add( path );
420 | getStructure( id ).add( path );
421 | }
422 |
423 | /**
424 | * Find a dependency that is similar from the specified dependency.
425 | *
426 | * @param dependency the dependency to find
427 | * @param dependencies a list of dependencies
428 | * @return a similar dependency or null if no similar dependency is found
429 | */
430 | private Dependency findDependency( Dependency dependency, List dependencies )
431 | {
432 | // CHECKSTYLE_OFF: LineLength
433 | for ( Dependency dep : dependencies )
434 | {
435 | if ( dependency.getGroupId().equals( dep.getGroupId() )
436 | && dependency.getArtifactId().equals( dep.getArtifactId() )
437 | && dependency.getType().equals( dep.getType() )
438 | && (
439 | ( dependency.getClassifier() == null && dep.getClassifier() == null )
440 | || ( dependency.getClassifier() != null && dependency.getClassifier().equals( dep.getClassifier() ) ) ) )
441 | {
442 | return dep;
443 | }
444 | }
445 | return null;
446 | // CHECKSTYLE_ON: LineLength
447 | }
448 |
449 | private Dependency matchDependency( List dependencies, Dependency dependency )
450 | {
451 | for ( Dependency dep : dependencies )
452 | {
453 | if ( WarUtils.dependencyEquals( dep, dependency ) )
454 | {
455 | return dep;
456 | }
457 |
458 | }
459 | return null;
460 | }
461 |
462 | private List createDependenciesInfoList( List dependencies )
463 | {
464 | if ( dependencies == null )
465 | {
466 | return Collections.emptyList();
467 | }
468 | final List result = new ArrayList();
469 | for ( Dependency dependency : dependencies )
470 | {
471 | result.add( new DependencyInfo( dependency ) );
472 | }
473 | return result;
474 | }
475 |
476 | private Object readResolve()
477 | {
478 | // the full structure should be resolved so let's rebuild it
479 | this.allFiles = new PathSet();
480 | for ( PathSet pathSet : registeredFiles.values() )
481 | {
482 | this.allFiles.addAll( pathSet );
483 | }
484 | return this;
485 | }
486 |
487 | /**
488 | * Callback interface to handle events related to filepath registration in the webapp.
489 | */
490 | public interface RegistrationCallback
491 | {
492 |
493 | /**
494 | * Called if the targetFilename for the specified ownerId has been registered successfully.
495 | *
496 | * This means that the targetFilename was unknown and has been registered successfully.
497 | *
498 | * @param ownerId the ownerId
499 | * @param targetFilename the relative path according to the root of the webapp
500 | * @throws IOException if an error occurred while handling this event
501 | */
502 | void registered( String ownerId, String targetFilename )
503 | throws IOException;
504 |
505 | /**
506 | * Called if the targetFilename for the specified ownerId has already been registered.
507 | *
508 | * This means that the targetFilename was known and belongs to the specified owner.
509 | *
510 | * @param ownerId the ownerId
511 | * @param targetFilename the relative path according to the root of the webapp
512 | * @throws IOException if an error occurred while handling this event
513 | */
514 | void alreadyRegistered( String ownerId, String targetFilename )
515 | throws IOException;
516 |
517 | /**
518 | * Called if the registration of the targetFilename for the specified ownerId has been refused
519 | * since the path already belongs to the actualOwnerId.
520 | *
521 | * This means that the targetFilename was known and does not belong to the specified owner.
522 | *
523 | * @param ownerId the ownerId
524 | * @param targetFilename the relative path according to the root of the webapp
525 | * @param actualOwnerId the actual owner
526 | * @throws IOException if an error occurred while handling this event
527 | */
528 | void refused( String ownerId, String targetFilename, String actualOwnerId )
529 | throws IOException;
530 |
531 | /**
532 | * Called if the targetFilename for the specified ownerId has been registered successfully by
533 | * superseding a deprecatedOwnerId, that is the previous owner of the file.
534 | *
535 | * This means that the targetFilename was known but for another owner. This usually happens after a
536 | * project's configuration change. As a result, the file has been registered successfully to the new owner.
537 | *
538 | * @param ownerId the ownerId
539 | * @param targetFilename the relative path according to the root of the webapp
540 | * @param deprecatedOwnerId the previous owner that does not exist anymore
541 | * @throws IOException if an error occurred while handling this event
542 | */
543 | void superseded( String ownerId, String targetFilename, String deprecatedOwnerId )
544 | throws IOException;
545 |
546 | /**
547 | * Called if the targetFilename for the specified ownerId has been registered successfully by
548 | * superseding a unknownOwnerId, that is an owner that does not exist anymore in the current project.
549 | *
550 | * This means that the targetFilename was known but for an owner that does not exist anymore. Hence the
551 | * file has been registered successfully to the new owner.
552 | *
553 | * @param ownerId the ownerId
554 | * @param targetFilename the relative path according to the root of the webapp
555 | * @param unknownOwnerId the previous owner that does not exist anymore
556 | * @throws IOException if an error occurred while handling this event
557 | */
558 | void supersededUnknownOwner( String ownerId, String targetFilename, String unknownOwnerId )
559 | throws IOException;
560 | }
561 |
562 | /**
563 | * Callback interface to handle events related to dependencies analysis.
564 | */
565 | public interface DependenciesAnalysisCallback
566 | {
567 |
568 | /**
569 | * Called if the dependency has not changed since the last build.
570 | *
571 | * @param dependency the dependency that hasn't changed
572 | */
573 | void unchangedDependency( Dependency dependency );
574 |
575 | /**
576 | * Called if a new dependency has been added since the last build.
577 | *
578 | * @param dependency the new dependency
579 | */
580 | void newDependency( Dependency dependency );
581 |
582 | /**
583 | * Called if the dependency has been removed since the last build.
584 | *
585 | * @param dependency the dependency that has been removed
586 | */
587 | void removedDependency( Dependency dependency );
588 |
589 | /**
590 | * Called if the version of the dependency has changed since the last build.
591 | *
592 | * @param dependency the dependency
593 | * @param previousVersion the previous version of the dependency
594 | */
595 | void updatedVersion( Dependency dependency, String previousVersion );
596 |
597 | /**
598 | * Called if the scope of the dependency has changed since the last build.
599 | *
600 | * @param dependency the dependency
601 | * @param previousScope the previous scope
602 | */
603 | void updatedScope( Dependency dependency, String previousScope );
604 |
605 | /**
606 | * Called if the optional flag of the dependency has changed since the last build.
607 | *
608 | * @param dependency the dependency
609 | * @param previousOptional the previous optional flag
610 | */
611 | void updatedOptionalFlag( Dependency dependency, boolean previousOptional );
612 |
613 | /**
614 | * Called if the dependency has been updated for unknown reason.
615 | *
616 | * @param dependency the dependency
617 | * @param previousDep the previous dependency
618 | */
619 | void updatedUnknown( Dependency dependency, Dependency previousDep );
620 |
621 | }
622 | }
623 |
--------------------------------------------------------------------------------