1 package org.apache.maven.plugin.jar;
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 org.apache.maven.archiver.MavenArchiveConfiguration;
24 import org.apache.maven.archiver.MavenArchiver;
25 import org.apache.maven.execution.MavenSession;
26 import org.apache.maven.plugin.AbstractMojo;
27 import org.apache.maven.plugin.MojoExecutionException;
28 import org.apache.maven.project.MavenProject;
29 import org.apache.maven.project.MavenProjectHelper;
30 import org.codehaus.plexus.archiver.jar.JarArchiver;
31
32 /**
33 * Base class for creating a jar from project classes.
34 *
35 * @author <a href="evenisse@apache.org">Emmanuel Venisse</a>
36 * @version $Id: AbstractJarMojo.java 1235468 2012-01-24 20:22:30Z krosenvold $
37 */
38 public abstract class AbstractJarMojo
39 extends AbstractMojo
40 {
41
42 private static final String[] DEFAULT_EXCLUDES = new String[] { "**/package.html" };
43
44 private static final String[] DEFAULT_INCLUDES = new String[] { "**/**" };
45
46 /**
47 * List of files to include. Specified as fileset patterns which are relative to the input directory whose contents
48 * is being packaged into the JAR.
49 *
50 * @parameter
51 */
52 private String[] includes;
53
54 /**
55 * List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents
56 * is being packaged into the JAR.
57 *
58 * @parameter
59 */
60 private String[] excludes;
61
62 /**
63 * Directory containing the generated JAR.
64 *
65 * @parameter default-value="${project.build.directory}"
66 * @required
67 */
68 private File outputDirectory;
69
70 /**
71 * Name of the generated JAR.
72 *
73 * @parameter alias="jarName" expression="${jar.finalName}" default-value="${project.build.finalName}"
74 * @required
75 */
76 private String finalName;
77
78 /**
79 * The Jar archiver.
80 *
81 * @component role="org.codehaus.plexus.archiver.Archiver" roleHint="jar"
82 */
83 private JarArchiver jarArchiver;
84
85 /**
86 * The Maven project.
87 *
88 * @parameter default-value="${project}"
89 * @required
90 * @readonly
91 */
92 private MavenProject project;
93
94 /**
95 * @parameter default-value="${session}"
96 * @readonly
97 * @required
98 */
99 private MavenSession session;
100
101 /**
102 * The archive configuration to use.
103 * See <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver Reference</a>.
104 *
105 * @parameter
106 */
107 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
108
109 /**
110 * Path to the default MANIFEST file to use. It will be used if
111 * <code>useDefaultManifestFile</code> is set to <code>true</code>.
112 *
113 * @parameter default-value="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
114 * @required
115 * @readonly
116 * @since 2.2
117 */
118 private File defaultManifestFile;
119
120 /**
121 * Set this to <code>true</code> to enable the use of the <code>defaultManifestFile</code>.
122 *
123 * @parameter expression="${jar.useDefaultManifestFile}" default-value="false"
124 *
125 * @since 2.2
126 */
127 private boolean useDefaultManifestFile;
128
129 /**
130 * @component
131 */
132 private MavenProjectHelper projectHelper;
133
134 /**
135 * Whether creating the archive should be forced.
136 *
137 * @parameter expression="${jar.forceCreation}" default-value="false"
138 */
139 private boolean forceCreation;
140
141 /**
142 * Skip creating empty archives
143 *
144 * @parameter expression="${jar.skipIfEmpty}" default-value="false"
145 */
146 private boolean skipIfEmpty;
147
148 /**
149 * Return the specific output directory to serve as the root for the archive.
150 */
151 protected abstract File getClassesDirectory();
152
153 protected final MavenProject getProject()
154 {
155 return project;
156 }
157
158 /**
159 * Overload this to produce a jar with another classifier, for example a test-jar.
160 */
161 protected abstract String getClassifier();
162
163 /**
164 * Overload this to produce a test-jar, for example.
165 */
166 protected abstract String getType();
167
168 protected static File getJarFile( File basedir, String finalName, String classifier )
169 {
170 if ( classifier == null )
171 {
172 classifier = "";
173 }
174 else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) )
175 {
176 classifier = "-" + classifier;
177 }
178
179 return new File( basedir, finalName + classifier + ".jar" );
180 }
181
182 /**
183 * Default Manifest location. Can point to a non existing file.
184 * Cannot return null.
185 */
186 protected File getDefaultManifestFile()
187 {
188 return defaultManifestFile;
189 }
190
191
192 /**
193 * Generates the JAR.
194 *
195 * @todo Add license files in META-INF directory.
196 */
197 public File createArchive()
198 throws MojoExecutionException
199 {
200 File jarFile = getJarFile( outputDirectory, finalName, getClassifier() );
201
202 MavenArchiver archiver = new MavenArchiver();
203
204 archiver.setArchiver( jarArchiver );
205
206 archiver.setOutputFile( jarFile );
207
208 archive.setForced( forceCreation );
209
210 try
211 {
212 File contentDirectory = getClassesDirectory();
213 if ( !contentDirectory.exists() )
214 {
215 getLog().warn( "JAR will be empty - no content was marked for inclusion!" );
216 }
217 else
218 {
219 archiver.getArchiver().addDirectory( contentDirectory, getIncludes(), getExcludes() );
220 }
221
222 File existingManifest = getDefaultManifestFile();
223
224 if ( useDefaultManifestFile && existingManifest.exists() && archive.getManifestFile() == null )
225 {
226 getLog().info( "Adding existing MANIFEST to archive. Found under: " + existingManifest.getPath() );
227 archive.setManifestFile( existingManifest );
228 }
229
230 archiver.createArchive( session, project, archive );
231
232 return jarFile;
233 }
234 catch ( Exception e )
235 {
236 // TODO: improve error handling
237 throw new MojoExecutionException( "Error assembling JAR", e );
238 }
239 }
240
241 /**
242 * Generates the JAR.
243 *
244 * @todo Add license files in META-INF directory.
245 */
246 public void execute()
247 throws MojoExecutionException
248 {
249 if ( skipIfEmpty && !getClassesDirectory().exists() )
250 {
251 getLog().info( "Skipping packaging of the test-jar" );
252 }
253 else
254 {
255 File jarFile = createArchive();
256
257 String classifier = getClassifier();
258 if ( classifier != null )
259 {
260 projectHelper.attachArtifact( getProject(), getType(), classifier, jarFile );
261 }
262 else
263 {
264 getProject().getArtifact().setFile( jarFile );
265 }
266 }
267 }
268
269 private String[] getIncludes()
270 {
271 if ( includes != null && includes.length > 0 )
272 {
273 return includes;
274 }
275 return DEFAULT_INCLUDES;
276 }
277
278 private String[] getExcludes()
279 {
280 if ( excludes != null && excludes.length > 0 )
281 {
282 return excludes;
283 }
284 return DEFAULT_EXCLUDES;
285 }
286 }