1 package org.apache.maven.plugins.install;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.io.Reader;
28 import java.io.Writer;
29 import java.nio.file.Files;
30 import java.util.Enumeration;
31 import java.util.jar.JarEntry;
32 import java.util.jar.JarFile;
33 import java.util.regex.Pattern;
34
35 import org.apache.maven.execution.MavenSession;
36 import org.apache.maven.model.Model;
37 import org.apache.maven.model.Parent;
38 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
39 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
40 import org.apache.maven.plugin.AbstractMojo;
41 import org.apache.maven.plugin.MojoExecutionException;
42 import org.apache.maven.plugin.MojoFailureException;
43 import org.apache.maven.plugins.annotations.Component;
44 import org.apache.maven.plugins.annotations.Mojo;
45 import org.apache.maven.plugins.annotations.Parameter;
46 import org.codehaus.plexus.util.FileUtils;
47 import org.codehaus.plexus.util.IOUtil;
48 import org.codehaus.plexus.util.StringUtils;
49 import org.codehaus.plexus.util.xml.XmlStreamReader;
50 import org.codehaus.plexus.util.xml.XmlStreamWriter;
51 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
52 import org.eclipse.aether.DefaultRepositoryCache;
53 import org.eclipse.aether.DefaultRepositorySystemSession;
54 import org.eclipse.aether.RepositorySystem;
55 import org.eclipse.aether.RepositorySystemSession;
56 import org.eclipse.aether.artifact.Artifact;
57 import org.eclipse.aether.artifact.ArtifactType;
58 import org.eclipse.aether.artifact.DefaultArtifact;
59 import org.eclipse.aether.installation.InstallRequest;
60 import org.eclipse.aether.installation.InstallationException;
61 import org.eclipse.aether.repository.LocalRepository;
62 import org.eclipse.aether.repository.LocalRepositoryManager;
63 import org.eclipse.aether.util.artifact.SubArtifact;
64
65
66
67
68
69
70 @Mojo( name = "install-file", requiresProject = false, aggregator = true, threadSafe = true )
71 public class InstallFileMojo
72 extends AbstractMojo
73 {
74 private static final String LS = System.getProperty( "line.separator" );
75
76 @Component
77 private RepositorySystem repositorySystem;
78
79 @Parameter( defaultValue = "${session}", required = true, readonly = true )
80 private MavenSession session;
81
82
83
84
85
86 @Parameter( property = "groupId" )
87 private String groupId;
88
89
90
91
92
93 @Parameter( property = "artifactId" )
94 private String artifactId;
95
96
97
98
99
100 @Parameter( property = "version" )
101 private String version;
102
103
104
105
106
107 @Parameter( property = "packaging" )
108 private String packaging;
109
110
111
112
113
114
115
116 @Parameter( property = "classifier" )
117 private String classifier;
118
119
120
121
122 @Parameter( property = "file", required = true )
123 private File file;
124
125
126
127
128
129
130 @Parameter( property = "javadoc" )
131 private File javadoc;
132
133
134
135
136
137
138 @Parameter( property = "sources" )
139 private File sources;
140
141
142
143
144
145
146
147 @Parameter( property = "pomFile" )
148 private File pomFile;
149
150
151
152
153
154
155
156 @Parameter( property = "generatePom" )
157 private Boolean generatePom;
158
159
160
161
162
163
164
165 @Parameter( property = "localRepositoryPath" )
166 private File localRepositoryPath;
167
168 @Override
169 public void execute()
170 throws MojoExecutionException, MojoFailureException
171 {
172 if ( !file.exists() )
173 {
174 String message = "The specified file '" + file.getPath() + "' does not exist";
175 getLog().error( message );
176 throw new MojoFailureException( message );
177 }
178
179 RepositorySystemSession repositorySystemSession = session.getRepositorySession();
180 if ( localRepositoryPath != null )
181 {
182
183 DefaultRepositorySystemSession newSession = new DefaultRepositorySystemSession(
184 session.getRepositorySession() );
185
186 newSession.setCache( new DefaultRepositoryCache() );
187
188 String contentType = newSession.getLocalRepository().getContentType();
189 if ( "enhanced".equals( contentType ) )
190 {
191 contentType = "default";
192 }
193 LocalRepositoryManager localRepositoryManager = repositorySystem.newLocalRepositoryManager( newSession,
194 new LocalRepository( localRepositoryPath, contentType ) );
195 newSession.setLocalRepositoryManager( localRepositoryManager );
196 repositorySystemSession = newSession;
197 getLog().debug( "localRepoPath: " + localRepositoryManager.getRepository().getBasedir() );
198 }
199
200 File temporaryPom = null;
201
202 if ( pomFile != null )
203 {
204 processModel( readModel( pomFile ) );
205 }
206 else
207 {
208 temporaryPom = readingPomFromJarFile();
209 pomFile = temporaryPom;
210 }
211
212 if ( groupId == null || artifactId == null || version == null || packaging == null )
213 {
214 throw new MojoExecutionException( "The artifact information is incomplete: 'groupId', 'artifactId', "
215 + "'version' and 'packaging' are required." );
216 }
217
218 if ( !isValidId( groupId )
219 || !isValidId( artifactId )
220 || !isValidVersion( version ) )
221 {
222 throw new MojoExecutionException( "The artifact information is not valid: uses invalid characters." );
223 }
224
225 InstallRequest installRequest = new InstallRequest();
226
227 boolean isFilePom = classifier == null && "pom".equals( packaging );
228 if ( !isFilePom )
229 {
230 ArtifactType artifactType = repositorySystemSession.getArtifactTypeRegistry().get( packaging );
231 if ( artifactType != null
232 && StringUtils.isEmpty( classifier )
233 && !StringUtils.isEmpty( artifactType.getClassifier() ) )
234 {
235 classifier = artifactType.getClassifier();
236 }
237 }
238 Artifact mainArtifact = new DefaultArtifact(
239 groupId,
240 artifactId,
241 classifier,
242 isFilePom ? "pom" : getExtension( file ),
243 version
244 ).setFile( file );
245 installRequest.addArtifact( mainArtifact );
246
247 File artifactLocalFile = getLocalRepositoryFile( session.getRepositorySession(), mainArtifact );
248 File pomLocalFile = getPomLocalRepositoryFile( session.getRepositorySession(), mainArtifact );
249
250 if ( file.equals( artifactLocalFile ) )
251 {
252 throw new MojoFailureException( "Cannot install artifact. "
253 + "Artifact is already in the local repository." + LS + LS + "File in question is: " + file + LS );
254 }
255
256 if ( !"pom".equals( packaging ) )
257 {
258 if ( pomFile != null )
259 {
260 installRequest.addArtifact( new SubArtifact( mainArtifact, "", "pom", pomFile ) );
261 }
262 else
263 {
264 if ( Boolean.TRUE.equals( generatePom ) || ( generatePom == null && !pomLocalFile.exists() ) )
265 {
266 temporaryPom = generatePomFile();
267 getLog().debug( "Installing generated POM" );
268 installRequest.addArtifact( new SubArtifact( mainArtifact, "", "pom", temporaryPom ) );
269 }
270 else if ( generatePom == null )
271 {
272 getLog().debug( "Skipping installation of generated POM, already present in local repository" );
273 }
274 }
275 }
276
277 if ( sources != null )
278 {
279 installRequest.addArtifact( new SubArtifact( mainArtifact, "sources", "jar", sources ) );
280 }
281
282 if ( javadoc != null )
283 {
284 installRequest.addArtifact( new SubArtifact( mainArtifact, "javadoc", "jar", javadoc ) );
285 }
286
287 try
288 {
289 repositorySystem.install( repositorySystemSession, installRequest );
290 }
291 catch ( InstallationException e )
292 {
293 throw new MojoExecutionException( e.getMessage(), e );
294 }
295 finally
296 {
297 if ( temporaryPom != null )
298 {
299
300 temporaryPom.delete();
301 }
302 }
303 }
304
305 private File readingPomFromJarFile()
306 throws MojoExecutionException
307 {
308 File pomFile = null;
309
310 JarFile jarFile = null;
311 try
312 {
313 Pattern pomEntry = Pattern.compile( "META-INF/maven/.*/pom\\.xml" );
314
315 jarFile = new JarFile( file );
316
317 Enumeration<JarEntry> jarEntries = jarFile.entries();
318
319 while ( jarEntries.hasMoreElements() )
320 {
321 JarEntry entry = jarEntries.nextElement();
322
323 if ( pomEntry.matcher( entry.getName() ).matches() )
324 {
325 getLog().debug( "Using " + entry.getName() + " as pomFile" );
326
327 InputStream pomInputStream = null;
328 OutputStream pomOutputStream = null;
329
330 try
331 {
332 pomInputStream = jarFile.getInputStream( entry );
333
334 String base = file.getName();
335 if ( base.indexOf( '.' ) > 0 )
336 {
337 base = base.substring( 0, base.lastIndexOf( '.' ) );
338 }
339 pomFile = File.createTempFile( base, ".pom" );
340
341 pomOutputStream = Files.newOutputStream( pomFile.toPath() );
342
343 IOUtil.copy( pomInputStream, pomOutputStream );
344
345 pomOutputStream.close();
346 pomOutputStream = null;
347
348 pomInputStream.close();
349 pomInputStream = null;
350
351 processModel( readModel( pomFile ) );
352
353 break;
354 }
355 finally
356 {
357 IOUtil.close( pomInputStream );
358 IOUtil.close( pomOutputStream );
359 }
360 }
361 }
362
363 if ( pomFile == null )
364 {
365 getLog().info( "pom.xml not found in " + file.getName() );
366 }
367 }
368 catch ( IOException e )
369 {
370
371 }
372 finally
373 {
374 if ( jarFile != null )
375 {
376 try
377 {
378 jarFile.close();
379 }
380 catch ( IOException e )
381 {
382
383 }
384 }
385 }
386 return pomFile;
387 }
388
389
390
391
392
393
394
395
396 private Model readModel( File pomFile )
397 throws MojoExecutionException
398 {
399 Reader reader = null;
400 try
401 {
402 reader = new XmlStreamReader( pomFile );
403 final Model model = new MavenXpp3Reader().read( reader );
404 reader.close();
405 reader = null;
406 return model;
407 }
408 catch ( FileNotFoundException e )
409 {
410 throw new MojoExecutionException( "File not found " + pomFile, e );
411 }
412 catch ( IOException e )
413 {
414 throw new MojoExecutionException( "Error reading POM " + pomFile, e );
415 }
416 catch ( XmlPullParserException e )
417 {
418 throw new MojoExecutionException( "Error parsing POM " + pomFile, e );
419 }
420 finally
421 {
422 IOUtil.close( reader );
423 }
424 }
425
426
427
428
429
430
431 private void processModel( Model model )
432 {
433 Parent parent = model.getParent();
434
435 if ( this.groupId == null )
436 {
437 this.groupId = model.getGroupId();
438 if ( this.groupId == null && parent != null )
439 {
440 this.groupId = parent.getGroupId();
441 }
442 }
443 if ( this.artifactId == null )
444 {
445 this.artifactId = model.getArtifactId();
446 }
447 if ( this.version == null )
448 {
449 this.version = model.getVersion();
450 if ( this.version == null && parent != null )
451 {
452 this.version = parent.getVersion();
453 }
454 }
455 if ( this.packaging == null )
456 {
457 this.packaging = model.getPackaging();
458 }
459 }
460
461
462
463
464
465
466 private Model generateModel()
467 {
468 Model model = new Model();
469
470 model.setModelVersion( "4.0.0" );
471
472 model.setGroupId( groupId );
473 model.setArtifactId( artifactId );
474 model.setVersion( version );
475 model.setPackaging( packaging );
476
477 model.setDescription( "POM was created from install:install-file" );
478
479 return model;
480 }
481
482
483
484
485
486
487
488
489 private File generatePomFile()
490 throws MojoExecutionException
491 {
492 Model model = generateModel();
493
494 Writer writer = null;
495 try
496 {
497 File pomFile = File.createTempFile( "mvninstall", ".pom" );
498
499 writer = new XmlStreamWriter( pomFile );
500 new MavenXpp3Writer().write( writer, model );
501 writer.close();
502 writer = null;
503
504 return pomFile;
505 }
506 catch ( IOException e )
507 {
508 throw new MojoExecutionException( "Error writing temporary POM file: " + e.getMessage(), e );
509 }
510 finally
511 {
512 IOUtil.close( writer );
513 }
514 }
515
516
517
518
519
520 private File getLocalRepositoryFile( RepositorySystemSession session, Artifact artifact )
521 {
522 String path = session.getLocalRepositoryManager().getPathForLocalArtifact( artifact );
523 return new File( session.getLocalRepository().getBasedir(), path );
524 }
525
526
527
528
529
530 private File getPomLocalRepositoryFile( RepositorySystemSession session, Artifact artifact )
531 {
532 SubArtifact pomArtifact = new SubArtifact( artifact, "", "pom" );
533 String path = session.getLocalRepositoryManager().getPathForLocalArtifact( pomArtifact );
534 return new File( session.getLocalRepository().getBasedir(), path );
535 }
536
537
538
539
540
541
542 private String getExtension( final File file )
543 {
544 String filename = file.getName();
545 if ( filename.contains( ".tar." ) )
546 {
547 return "tar." + FileUtils.getExtension( filename );
548 }
549 else
550 {
551 return FileUtils.getExtension( filename );
552 }
553 }
554
555
556
557
558 private boolean isValidId( String id )
559 {
560 if ( id == null )
561 {
562 return false;
563 }
564 for ( int i = 0; i < id.length(); i++ )
565 {
566 char c = id.charAt( i );
567 if ( !( c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'
568 || c >= '0' && c <= '9' || c == '-' || c == '_' || c == '.' ) )
569 {
570 return false;
571 }
572 }
573 return true;
574 }
575
576 private static final String ILLEGAL_VERSION_CHARS = "\\/:\"<>|?*[](){},";
577
578
579
580
581 private boolean isValidVersion( String version )
582 {
583 if ( version == null )
584 {
585 return false;
586 }
587 for ( int i = version.length() - 1; i >= 0; i-- )
588 {
589 if ( ILLEGAL_VERSION_CHARS.indexOf( version.charAt( i ) ) >= 0 )
590 {
591 return false;
592 }
593 }
594 return true;
595 }
596
597 }