1 package org.apache.maven.plugins.repository;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.factory.ArtifactFactory;
24 import org.apache.maven.artifact.repository.ArtifactRepository;
25 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
26 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
27 import org.apache.maven.artifact.resolver.ArtifactResolver;
28 import org.apache.maven.model.License;
29 import org.apache.maven.model.Model;
30 import org.apache.maven.model.Scm;
31 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
32 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
33 import org.apache.maven.plugin.AbstractMojo;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugins.annotations.Component;
36 import org.apache.maven.plugins.annotations.Mojo;
37 import org.apache.maven.plugins.annotations.Parameter;
38 import org.apache.maven.settings.Settings;
39 import org.codehaus.plexus.archiver.Archiver;
40 import org.codehaus.plexus.archiver.ArchiverException;
41 import org.codehaus.plexus.archiver.jar.JarArchiver;
42 import org.codehaus.plexus.components.interactivity.InputHandler;
43 import org.codehaus.plexus.util.ReaderFactory;
44 import org.codehaus.plexus.util.WriterFactory;
45 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
46
47 import java.io.File;
48 import java.io.FileNotFoundException;
49 import java.io.IOException;
50 import java.util.Collections;
51 import java.util.List;
52
53
54
55
56
57
58
59
60
61
62 @Mojo( name = "bundle-pack", requiresProject = false )
63 public class BundlePackMojo
64 extends AbstractMojo
65 {
66 public static final String POM = "pom.xml";
67
68
69
70
71 @Component( role = Archiver.class, hint = "jar" )
72 protected JarArchiver jarArchiver;
73
74
75
76
77 @Component
78 protected ArtifactResolver artifactResolver;
79
80
81
82
83 @Component
84 protected ArtifactFactory artifactFactory;
85
86
87
88
89 @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
90 protected ArtifactRepository localRepository;
91
92
93
94 @Component
95 protected InputHandler inputHandler;
96
97
98
99
100 @Parameter( defaultValue = "${basedir}", readonly = true )
101 protected String basedir;
102
103
104
105
106 @Parameter( property = "groupId" )
107 protected String groupId;
108
109
110
111
112 @Parameter( property = "artifactId" )
113 protected String artifactId;
114
115
116
117
118 @Parameter( property = "version" )
119 protected String version;
120
121
122
123
124 @Parameter( property = "scmUrl" )
125 protected String scmUrl;
126
127
128
129
130
131
132
133
134 @Parameter( property = "scmConnection" )
135 protected String scmConnection;
136
137
138
139 @Parameter( defaultValue = "${settings}", readonly = true, required = true )
140 protected Settings settings;
141
142
143
144
145
146
147 @Parameter( property = "bundle.disableMaterialization", defaultValue = "false" )
148 private boolean disableMaterialization;
149
150 @SuppressWarnings( "unchecked" )
151 public void execute()
152 throws MojoExecutionException
153 {
154 readArtifactDataFromUser();
155
156 Artifact artifact = artifactFactory.createProjectArtifact( groupId, artifactId, version );
157
158 try
159 {
160 artifactResolver.resolve( artifact, Collections.EMPTY_LIST, localRepository );
161 }
162 catch ( ArtifactResolutionException e )
163 {
164 throw new MojoExecutionException( "Unable to resolve artifact " + artifact.getId(), e );
165 }
166 catch ( ArtifactNotFoundException e )
167 {
168 throw new MojoExecutionException( "Artifact " + artifact.getId() + " not found in local repository", e );
169 }
170
171 File pom = artifact.getFile();
172
173 File dir = pom.getParentFile();
174
175 Model model = readPom( pom );
176
177 boolean rewrite = false;
178 try
179 {
180
181 if ( model.getPackaging() == null )
182 {
183 model.setPackaging( "jar" );
184 rewrite = true;
185 }
186 if ( model.getName() == null )
187 {
188 getLog().info( "Project name is missing, please type the project name [" + artifactId + "]:" );
189 model.setName( inputHandler.readLine() );
190 if ( model.getName() == null )
191 {
192 model.setName( artifactId );
193 }
194 rewrite = true;
195 }
196 if ( model.getDescription() == null )
197 {
198 getLog().info( "Project description is missing, please type the project description:" );
199 model.setDescription( inputHandler.readLine() );
200 rewrite = true;
201 }
202 if ( model.getUrl() == null )
203 {
204 getLog().info( "Project URL is missing, please type the project URL:" );
205 model.setUrl( inputHandler.readLine() );
206 rewrite = true;
207 }
208
209 List<License> licenses = model.getLicenses();
210 if ( licenses.isEmpty() )
211 {
212 License license = new License();
213
214 getLog().info( "License name is missing, please type the license name:" );
215 license.setName( inputHandler.readLine() );
216 getLog().info( "License URL is missing, please type the license URL:" );
217 license.setUrl( inputHandler.readLine() );
218 licenses.add( license );
219 rewrite = true;
220 }
221
222 if ( disableMaterialization )
223 {
224 getLog().warn( "Validations to confirm support for project materialization have been DISABLED."
225 + "\n\nYour project may not provide the POM elements necessary to allow users to retrieve "
226 + "sources on-demand,"
227 + "\nor to easily checkout your project in an IDE. THIS CAN SERIOUSLY INCONVENIENCE YOUR USERS."
228 + "\n\nContinue? [y/N]" );
229
230 try
231 {
232 if ( 'y' != inputHandler.readLine().toLowerCase().charAt( 0 ) )
233 {
234 disableMaterialization = false;
235 }
236 }
237 catch ( IOException e )
238 {
239 getLog().debug( "Error reading confirmation: " + e.getMessage(), e );
240 }
241
242 }
243
244 if ( !disableMaterialization )
245 {
246 Scm scm = model.getScm();
247 if ( scm == null )
248 {
249 scm = new Scm();
250 model.setScm( scm );
251 }
252
253 if ( scm.getUrl() == null )
254 {
255 if ( scmUrl != null )
256 {
257 scm.setUrl( scmUrl );
258 }
259 else
260 {
261 getLog().info( "SCM view URL is missing, please type the URL for the viewable SCM interface:" );
262 scm.setUrl( inputHandler.readLine() );
263 rewrite = true;
264 }
265 }
266
267 if ( scm.getConnection() == null )
268 {
269 if ( scmConnection != null )
270 {
271 scm.setConnection( scmConnection );
272 }
273 else
274 {
275 getLog().info( "SCM read-only connection URL is missing, please type the read-only SCM URL:" );
276 scm.setConnection( inputHandler.readLine() );
277 rewrite = true;
278 }
279 }
280 }
281 }
282 catch ( IOException e )
283 {
284 throw new MojoExecutionException( e.getMessage(), e );
285 }
286
287 try
288 {
289 if ( rewrite )
290 {
291 new MavenXpp3Writer().write( WriterFactory.newXmlWriter( pom ), model );
292 }
293
294 String finalName = null;
295
296 if ( model.getBuild() != null )
297 {
298 finalName = model.getBuild().getFinalName();
299 }
300 if ( finalName == null )
301 {
302 finalName = model.getArtifactId() + "-" + model.getVersion();
303 }
304
305 boolean batchMode = settings == null ? false : !settings.isInteractiveMode();
306 List<File> files = BundleUtils.selectProjectFiles( dir, inputHandler, finalName, pom, getLog(), batchMode );
307
308 File bundle = new File( basedir, finalName + "-bundle.jar" );
309
310 jarArchiver.addFile( pom, POM );
311
312 boolean artifactChecks = !"pom".equals( model.getPackaging() );
313 boolean sourcesFound = false;
314 boolean javadocsFound = false;
315
316 for ( File f : files )
317 {
318 if ( artifactChecks && f.getName().endsWith( finalName + "-sources.jar" ) )
319 {
320 sourcesFound = true;
321 }
322 else if ( artifactChecks && f.getName().equals( finalName + "-javadoc.jar" ) )
323 {
324 javadocsFound = true;
325 }
326
327 jarArchiver.addFile( f, f.getName() );
328 }
329
330 if ( artifactChecks && !sourcesFound )
331 {
332 getLog().warn( "Sources not included in upload bundle." );
333 }
334
335 if ( artifactChecks && !javadocsFound )
336 {
337 getLog().warn( "Javadoc not included in upload bundle." );
338 }
339
340 jarArchiver.setDestFile( bundle );
341
342 jarArchiver.createArchive();
343
344 }
345 catch ( IOException e )
346 {
347 throw new MojoExecutionException( e.getMessage(), e );
348 }
349 catch ( ArchiverException e )
350 {
351 throw new MojoExecutionException( e.getMessage(), e );
352 }
353
354 }
355
356
357
358
359
360
361
362 private void readArtifactDataFromUser()
363 throws MojoExecutionException
364 {
365 try
366 {
367 if ( groupId == null )
368 {
369 getLog().info( "groupId? " );
370
371 groupId = inputHandler.readLine();
372
373 }
374
375 if ( artifactId == null )
376 {
377 getLog().info( "artifactId? " );
378 artifactId = inputHandler.readLine();
379 }
380
381 if ( version == null )
382 {
383 getLog().info( "version? " );
384 version = inputHandler.readLine();
385 }
386 }
387 catch ( IOException e )
388 {
389 throw new MojoExecutionException( e.getMessage(), e );
390 }
391 }
392
393
394
395
396
397
398
399
400 private Model readPom( File pom )
401 throws MojoExecutionException
402 {
403 Model model;
404 try
405 {
406 model = new MavenXpp3Reader().read( ReaderFactory.newXmlReader( pom ) );
407 }
408 catch ( XmlPullParserException e )
409 {
410 throw new MojoExecutionException( "Unable to parse POM at " + pom.getAbsolutePath() + ": " + e.getMessage(),
411 e );
412 }
413 catch ( FileNotFoundException e )
414 {
415 throw new MojoExecutionException( "Unable to read POM at " + pom.getAbsolutePath() + ": " + e.getMessage(),
416 e );
417 }
418 catch ( IOException e )
419 {
420 throw new MojoExecutionException( "Unable to read POM at " + pom.getAbsolutePath() + ": " + e.getMessage(),
421 e );
422 }
423 return model;
424 }
425
426 }