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 if ( !Boolean.TRUE.equals( generatePom ) )
210 {
211 pomFile = temporaryPom;
212 getLog().debug( "Using JAR embedded POM as pomFile" );
213 }
214 }
215
216 if ( groupId == null || artifactId == null || version == null || packaging == null )
217 {
218 throw new MojoExecutionException( "The artifact information is incomplete: 'groupId', 'artifactId', "
219 + "'version' and 'packaging' are required." );
220 }
221
222 if ( !isValidId( groupId )
223 || !isValidId( artifactId )
224 || !isValidVersion( version ) )
225 {
226 throw new MojoExecutionException( "The artifact information is not valid: uses invalid characters." );
227 }
228
229 InstallRequest installRequest = new InstallRequest();
230
231 boolean isFilePom = classifier == null && "pom".equals( packaging );
232 if ( !isFilePom )
233 {
234 ArtifactType artifactType = repositorySystemSession.getArtifactTypeRegistry().get( packaging );
235 if ( artifactType != null
236 && StringUtils.isEmpty( classifier )
237 && !StringUtils.isEmpty( artifactType.getClassifier() ) )
238 {
239 classifier = artifactType.getClassifier();
240 }
241 }
242 Artifact mainArtifact = new DefaultArtifact(
243 groupId,
244 artifactId,
245 classifier,
246 isFilePom ? "pom" : getExtension( file ),
247 version
248 ).setFile( file );
249 installRequest.addArtifact( mainArtifact );
250
251 File artifactLocalFile = getLocalRepositoryFile( session.getRepositorySession(), mainArtifact );
252 File pomLocalFile = getPomLocalRepositoryFile( session.getRepositorySession(), mainArtifact );
253
254 if ( file.equals( artifactLocalFile ) )
255 {
256 throw new MojoFailureException( "Cannot install artifact. "
257 + "Artifact is already in the local repository." + LS + LS + "File in question is: " + file + LS );
258 }
259
260 if ( !"pom".equals( packaging ) )
261 {
262 if ( pomFile != null )
263 {
264 installRequest.addArtifact( new SubArtifact( mainArtifact, "", "pom", pomFile ) );
265 }
266 else
267 {
268 if ( Boolean.TRUE.equals( generatePom ) || ( generatePom == null && !pomLocalFile.exists() ) )
269 {
270 temporaryPom = generatePomFile();
271 getLog().debug( "Installing generated POM" );
272 installRequest.addArtifact( new SubArtifact( mainArtifact, "", "pom", temporaryPom ) );
273 }
274 else if ( generatePom == null )
275 {
276 getLog().debug( "Skipping installation of generated POM, already present in local repository" );
277 }
278 }
279 }
280
281 if ( sources != null )
282 {
283 installRequest.addArtifact( new SubArtifact( mainArtifact, "sources", "jar", sources ) );
284 }
285
286 if ( javadoc != null )
287 {
288 installRequest.addArtifact( new SubArtifact( mainArtifact, "javadoc", "jar", javadoc ) );
289 }
290
291 try
292 {
293 repositorySystem.install( repositorySystemSession, installRequest );
294 }
295 catch ( InstallationException e )
296 {
297 throw new MojoExecutionException( e.getMessage(), e );
298 }
299 finally
300 {
301 if ( temporaryPom != null )
302 {
303
304 temporaryPom.delete();
305 }
306 }
307 }
308
309 private File readingPomFromJarFile()
310 throws MojoExecutionException
311 {
312 File pomFile = null;
313
314 JarFile jarFile = null;
315 try
316 {
317 Pattern pomEntry = Pattern.compile( "META-INF/maven/.*/pom\\.xml" );
318
319 jarFile = new JarFile( file );
320
321 Enumeration<JarEntry> jarEntries = jarFile.entries();
322
323 while ( jarEntries.hasMoreElements() )
324 {
325 JarEntry entry = jarEntries.nextElement();
326
327 if ( pomEntry.matcher( entry.getName() ).matches() )
328 {
329 getLog().debug( "Loading " + entry.getName() );
330
331 InputStream pomInputStream = null;
332 OutputStream pomOutputStream = null;
333
334 try
335 {
336 pomInputStream = jarFile.getInputStream( entry );
337
338 String base = file.getName();
339 if ( base.indexOf( '.' ) > 0 )
340 {
341 base = base.substring( 0, base.lastIndexOf( '.' ) );
342 }
343 pomFile = File.createTempFile( base, ".pom" );
344
345 pomOutputStream = Files.newOutputStream( pomFile.toPath() );
346
347 IOUtil.copy( pomInputStream, pomOutputStream );
348
349 pomOutputStream.close();
350 pomOutputStream = null;
351
352 pomInputStream.close();
353 pomInputStream = null;
354
355 processModel( readModel( pomFile ) );
356
357 break;
358 }
359 finally
360 {
361 IOUtil.close( pomInputStream );
362 IOUtil.close( pomOutputStream );
363 }
364 }
365 }
366
367 if ( pomFile == null )
368 {
369 getLog().info( "pom.xml not found in " + file.getName() );
370 }
371 }
372 catch ( IOException e )
373 {
374
375 }
376 finally
377 {
378 if ( jarFile != null )
379 {
380 try
381 {
382 jarFile.close();
383 }
384 catch ( IOException e )
385 {
386
387 }
388 }
389 }
390 return pomFile;
391 }
392
393
394
395
396
397
398
399
400 private Model readModel( File pomFile )
401 throws MojoExecutionException
402 {
403 Reader reader = null;
404 try
405 {
406 reader = new XmlStreamReader( pomFile );
407 final Model model = new MavenXpp3Reader().read( reader );
408 reader.close();
409 reader = null;
410 return model;
411 }
412 catch ( FileNotFoundException e )
413 {
414 throw new MojoExecutionException( "File not found " + pomFile, e );
415 }
416 catch ( IOException e )
417 {
418 throw new MojoExecutionException( "Error reading POM " + pomFile, e );
419 }
420 catch ( XmlPullParserException e )
421 {
422 throw new MojoExecutionException( "Error parsing POM " + pomFile, e );
423 }
424 finally
425 {
426 IOUtil.close( reader );
427 }
428 }
429
430
431
432
433
434
435 private void processModel( Model model )
436 {
437 Parent parent = model.getParent();
438
439 if ( this.groupId == null )
440 {
441 this.groupId = model.getGroupId();
442 if ( this.groupId == null && parent != null )
443 {
444 this.groupId = parent.getGroupId();
445 }
446 }
447 if ( this.artifactId == null )
448 {
449 this.artifactId = model.getArtifactId();
450 }
451 if ( this.version == null )
452 {
453 this.version = model.getVersion();
454 if ( this.version == null && parent != null )
455 {
456 this.version = parent.getVersion();
457 }
458 }
459 if ( this.packaging == null )
460 {
461 this.packaging = model.getPackaging();
462 }
463 }
464
465
466
467
468
469
470 private Model generateModel()
471 {
472 Model model = new Model();
473
474 model.setModelVersion( "4.0.0" );
475
476 model.setGroupId( groupId );
477 model.setArtifactId( artifactId );
478 model.setVersion( version );
479 model.setPackaging( packaging );
480
481 model.setDescription( "POM was created from install:install-file" );
482
483 return model;
484 }
485
486
487
488
489
490
491
492
493 private File generatePomFile()
494 throws MojoExecutionException
495 {
496 Model model = generateModel();
497
498 Writer writer = null;
499 try
500 {
501 File pomFile = File.createTempFile( "mvninstall", ".pom" );
502
503 writer = new XmlStreamWriter( pomFile );
504 new MavenXpp3Writer().write( writer, model );
505 writer.close();
506 writer = null;
507
508 return pomFile;
509 }
510 catch ( IOException e )
511 {
512 throw new MojoExecutionException( "Error writing temporary POM file: " + e.getMessage(), e );
513 }
514 finally
515 {
516 IOUtil.close( writer );
517 }
518 }
519
520
521
522
523
524 private File getLocalRepositoryFile( RepositorySystemSession session, Artifact artifact )
525 {
526 String path = session.getLocalRepositoryManager().getPathForLocalArtifact( artifact );
527 return new File( session.getLocalRepository().getBasedir(), path );
528 }
529
530
531
532
533
534 private File getPomLocalRepositoryFile( RepositorySystemSession session, Artifact artifact )
535 {
536 SubArtifact pomArtifact = new SubArtifact( artifact, "", "pom" );
537 String path = session.getLocalRepositoryManager().getPathForLocalArtifact( pomArtifact );
538 return new File( session.getLocalRepository().getBasedir(), path );
539 }
540
541
542
543
544
545
546 private String getExtension( final File file )
547 {
548 String filename = file.getName();
549 if ( filename.contains( ".tar." ) )
550 {
551 return "tar." + FileUtils.getExtension( filename );
552 }
553 else
554 {
555 return FileUtils.getExtension( filename );
556 }
557 }
558
559
560
561
562 private boolean isValidId( String id )
563 {
564 if ( id == null )
565 {
566 return false;
567 }
568 for ( int i = 0; i < id.length(); i++ )
569 {
570 char c = id.charAt( i );
571 if ( !( c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'
572 || c >= '0' && c <= '9' || c == '-' || c == '_' || c == '.' ) )
573 {
574 return false;
575 }
576 }
577 return true;
578 }
579
580 private static final String ILLEGAL_VERSION_CHARS = "\\/:\"<>|?*[](){},";
581
582
583
584
585 private boolean isValidVersion( String version )
586 {
587 if ( version == null )
588 {
589 return false;
590 }
591 for ( int i = version.length() - 1; i >= 0; i-- )
592 {
593 if ( ILLEGAL_VERSION_CHARS.indexOf( version.charAt( i ) ) >= 0 )
594 {
595 return false;
596 }
597 }
598 return true;
599 }
600
601 }