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 org.apache.maven.archiver.MavenArchiveConfiguration;
23 import org.apache.maven.archiver.MavenArchiver;
24 import org.apache.maven.plugin.AbstractMojo;
25 import org.apache.maven.plugin.MojoExecutionException;
26 import org.apache.maven.project.MavenProject;
27 import org.apache.maven.project.MavenProjectHelper;
28 import org.codehaus.plexus.archiver.jar.JarArchiver;
29
30 import java.io.File;
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 1158941 2011-08-17 22:22:17Z rfscholte $
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 * The archive configuration to use.
96 * See <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver Reference</a>.
97 *
98 * @parameter
99 */
100 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
101
102 /**
103 * Path to the default MANIFEST file to use. It will be used if
104 * <code>useDefaultManifestFile</code> is set to <code>true</code>.
105 *
106 * @parameter default-value="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
107 * @required
108 * @readonly
109 * @since 2.2
110 */
111 private File defaultManifestFile;
112
113 /**
114 * Set this to <code>true</code> to enable the use of the <code>defaultManifestFile</code>.
115 *
116 * @parameter expression="${jar.useDefaultManifestFile}" default-value="false"
117 *
118 * @since 2.2
119 */
120 private boolean useDefaultManifestFile;
121
122 /**
123 * @component
124 */
125 private MavenProjectHelper projectHelper;
126
127 /**
128 * Whether creating the archive should be forced.
129 *
130 * @parameter expression="${jar.forceCreation}" default-value="false"
131 */
132 private boolean forceCreation;
133
134 /**
135 * Return the specific output directory to serve as the root for the archive.
136 */
137 protected abstract File getClassesDirectory();
138
139 protected final MavenProject getProject()
140 {
141 return project;
142 }
143
144 /**
145 * Overload this to produce a jar with another classifier, for example a test-jar.
146 */
147 protected abstract String getClassifier();
148
149 /**
150 * Overload this to produce a test-jar, for example.
151 */
152 protected abstract String getType();
153
154 protected static File getJarFile( File basedir, String finalName, String classifier )
155 {
156 if ( classifier == null )
157 {
158 classifier = "";
159 }
160 else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) )
161 {
162 classifier = "-" + classifier;
163 }
164
165 return new File( basedir, finalName + classifier + ".jar" );
166 }
167
168 /**
169 * Default Manifest location. Can point to a non existing file.
170 * Cannot return null.
171 */
172 protected File getDefaultManifestFile()
173 {
174 return defaultManifestFile;
175 }
176
177
178 /**
179 * Generates the JAR.
180 *
181 * @todo Add license files in META-INF directory.
182 */
183 public File createArchive()
184 throws MojoExecutionException
185 {
186 File jarFile = getJarFile( outputDirectory, finalName, getClassifier() );
187
188 MavenArchiver archiver = new MavenArchiver();
189
190 archiver.setArchiver( jarArchiver );
191
192 archiver.setOutputFile( jarFile );
193
194 archive.setForced( forceCreation );
195
196 try
197 {
198 File contentDirectory = getClassesDirectory();
199 if ( !contentDirectory.exists() )
200 {
201 getLog().warn( "JAR will be empty - no content was marked for inclusion!" );
202 }
203 else
204 {
205 archiver.getArchiver().addDirectory( contentDirectory, getIncludes(), getExcludes() );
206 }
207
208 File existingManifest = getDefaultManifestFile();
209
210 if ( useDefaultManifestFile && existingManifest.exists() && archive.getManifestFile() == null )
211 {
212 getLog().info( "Adding existing MANIFEST to archive. Found under: " + existingManifest.getPath() );
213 archive.setManifestFile( existingManifest );
214 }
215
216 archiver.createArchive( project, archive );
217
218 return jarFile;
219 }
220 catch ( Exception e )
221 {
222 // TODO: improve error handling
223 throw new MojoExecutionException( "Error assembling JAR", e );
224 }
225 }
226
227 /**
228 * Generates the JAR.
229 *
230 * @todo Add license files in META-INF directory.
231 */
232 public void execute()
233 throws MojoExecutionException
234 {
235 File jarFile = createArchive();
236
237 String classifier = getClassifier();
238 if ( classifier != null )
239 {
240 projectHelper.attachArtifact( getProject(), getType(), classifier, jarFile );
241 }
242 else
243 {
244 getProject().getArtifact().setFile( jarFile );
245 }
246 }
247
248 private String[] getIncludes()
249 {
250 if ( includes != null && includes.length > 0 )
251 {
252 return includes;
253 }
254 return DEFAULT_INCLUDES;
255 }
256
257 private String[] getExcludes()
258 {
259 if ( excludes != null && excludes.length > 0 )
260 {
261 return excludes;
262 }
263 return DEFAULT_EXCLUDES;
264 }
265 }