1 package org.apache.maven.plugins.deploy;
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.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.io.Reader;
29 import java.io.Writer;
30 import java.util.ArrayList;
31 import java.util.Enumeration;
32 import java.util.List;
33 import java.util.jar.JarEntry;
34 import java.util.jar.JarFile;
35 import java.util.regex.Pattern;
36
37 import org.apache.maven.artifact.Artifact;
38 import org.apache.maven.artifact.repository.ArtifactRepository;
39 import org.apache.maven.model.Model;
40 import org.apache.maven.model.Parent;
41 import org.apache.maven.model.building.ModelBuildingException;
42 import org.apache.maven.model.building.ModelSource;
43 import org.apache.maven.model.building.StringModelSource;
44 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
45 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
46 import org.apache.maven.plugin.MojoExecutionException;
47 import org.apache.maven.plugin.MojoFailureException;
48 import org.apache.maven.plugins.annotations.Component;
49 import org.apache.maven.plugins.annotations.Mojo;
50 import org.apache.maven.plugins.annotations.Parameter;
51 import org.apache.maven.project.DefaultProjectBuildingRequest;
52 import org.apache.maven.project.MavenProject;
53 import org.apache.maven.project.MavenProjectHelper;
54 import org.apache.maven.project.ProjectBuilder;
55 import org.apache.maven.project.ProjectBuildingException;
56 import org.apache.maven.project.artifact.ProjectArtifactMetadata;
57 import org.apache.maven.shared.transfer.artifact.DefaultArtifactCoordinate;
58 import org.apache.maven.shared.transfer.artifact.deploy.ArtifactDeployer;
59 import org.apache.maven.shared.transfer.artifact.deploy.ArtifactDeployerException;
60 import org.apache.maven.shared.transfer.repository.RepositoryManager;
61 import org.apache.maven.shared.utils.Os;
62 import org.codehaus.plexus.util.FileUtils;
63 import org.codehaus.plexus.util.IOUtil;
64 import org.codehaus.plexus.util.ReaderFactory;
65 import org.codehaus.plexus.util.StringUtils;
66 import org.codehaus.plexus.util.WriterFactory;
67 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
68
69
70
71
72
73
74 @Mojo( name = "deploy-file", requiresProject = false, threadSafe = true )
75 public class DeployFileMojo
76 extends AbstractDeployMojo
77 {
78 @Component
79 private ArtifactDeployer artifactDeployer;
80
81
82
83
84 @Component
85 private MavenProjectHelper projectHelper;
86
87
88
89
90 @Component
91 private ProjectBuilder projectBuilder;
92
93
94
95
96 @Parameter( property = "groupId" )
97 private String groupId;
98
99
100
101
102 @Parameter( property = "artifactId" )
103 private String artifactId;
104
105
106
107
108 @Parameter( property = "version" )
109 private String version;
110
111
112
113
114
115
116
117 @Parameter( property = "packaging" )
118 private String packaging;
119
120
121
122
123 @Parameter( property = "generatePom.description" )
124 private String description;
125
126
127
128
129 @Parameter( property = "file", required = true )
130 private File file;
131
132
133
134
135
136
137 @Parameter( property = "javadoc" )
138 private File javadoc;
139
140
141
142
143
144
145 @Parameter( property = "sources" )
146 private File sources;
147
148
149
150
151
152 @Parameter( property = "repositoryId", defaultValue = "remote-repository", required = true )
153 private String repositoryId;
154
155
156
157
158
159 @Parameter( property = "url", required = true )
160 private String url;
161
162
163
164
165 @Parameter( property = "pomFile" )
166 private File pomFile;
167
168
169
170
171 @Parameter( property = "generatePom", defaultValue = "true" )
172 private boolean generatePom;
173
174
175
176
177 @Parameter( property = "classifier" )
178 private String classifier;
179
180
181
182
183
184
185
186 @Parameter( property = "uniqueVersion" )
187 @Deprecated
188 private Boolean uniqueVersion;
189
190
191
192
193
194 @Parameter( property = "types" )
195 private String types;
196
197
198
199
200
201 @Parameter( property = "classifiers" )
202 private String classifiers;
203
204
205
206
207
208 @Parameter( property = "files" )
209 private String files;
210
211 @Component
212 private RepositoryManager repoManager;
213
214 void initProperties()
215 throws MojoExecutionException
216 {
217 if ( pomFile == null )
218 {
219 boolean foundPom = false;
220
221 JarFile jarFile = null;
222 try
223 {
224 Pattern pomEntry = Pattern.compile( "META-INF/maven/.*/pom\\.xml" );
225
226 jarFile = new JarFile( file );
227
228 Enumeration<JarEntry> jarEntries = jarFile.entries();
229
230 while ( jarEntries.hasMoreElements() )
231 {
232 JarEntry entry = jarEntries.nextElement();
233
234 if ( pomEntry.matcher( entry.getName() ).matches() )
235 {
236 getLog().debug( "Using " + entry.getName() + " as pomFile" );
237
238 foundPom = true;
239
240 InputStream pomInputStream = null;
241 OutputStream pomOutputStream = null;
242
243 try
244 {
245 pomInputStream = jarFile.getInputStream( entry );
246
247 String base = file.getName();
248 if ( base.indexOf( '.' ) > 0 )
249 {
250 base = base.substring( 0, base.lastIndexOf( '.' ) );
251 }
252 pomFile = new File( file.getParentFile(), base + ".pom" );
253
254 pomOutputStream = new FileOutputStream( pomFile );
255
256 IOUtil.copy( pomInputStream, pomOutputStream );
257
258 pomOutputStream.close();
259 pomOutputStream = null;
260 pomInputStream.close();
261 pomInputStream = null;
262
263 processModel( readModel( pomFile ) );
264
265 break;
266 }
267 finally
268 {
269 IOUtil.close( pomInputStream );
270 IOUtil.close( pomOutputStream );
271 }
272 }
273 }
274
275 if ( !foundPom )
276 {
277 getLog().info( "pom.xml not found in " + file.getName() );
278 }
279 }
280 catch ( IOException e )
281 {
282
283 }
284 finally
285 {
286 if ( jarFile != null )
287 {
288 try
289 {
290 jarFile.close();
291 }
292 catch ( IOException e )
293 {
294
295 }
296 }
297 }
298 }
299 else
300 {
301 processModel( readModel( pomFile ) );
302 }
303
304 if ( packaging == null && file != null )
305 {
306 packaging = FileUtils.getExtension( file.getName() );
307 }
308 }
309
310 public void execute()
311 throws MojoExecutionException, MojoFailureException
312 {
313 if ( uniqueVersion != null )
314 {
315 throw new MojoExecutionException( "You are using 'uniqueVersion' which has been removed"
316 + " from the maven-deploy-plugin. "
317 + "Please see the >>Major Version Upgrade to version 3.0.0<< on the plugin site." );
318 }
319
320 failIfOffline();
321
322 if ( !file.exists() )
323 {
324 throw new MojoExecutionException( file.getPath() + " not found." );
325 }
326
327 initProperties();
328
329 ArtifactRepository deploymentRepository = createDeploymentArtifactRepository( repositoryId, url );
330
331 String protocol = deploymentRepository.getProtocol();
332
333 if ( StringUtils.isEmpty( protocol ) )
334 {
335 throw new MojoExecutionException( "No transfer protocol found." );
336 }
337
338 MavenProject project = createMavenProject();
339 Artifact artifact = project.getArtifact();
340
341 if ( file.equals( getLocalRepoFile() ) )
342 {
343 throw new MojoFailureException( "Cannot deploy artifact from the local repository: " + file );
344 }
345
346 List<Artifact> deployableArtifacts = new ArrayList<Artifact>();
347
348 if ( classifier == null )
349 {
350 artifact.setFile( file );
351 deployableArtifacts.add( artifact );
352 }
353 else
354 {
355 projectHelper.attachArtifact( project, packaging, classifier, file );
356 }
357
358
359 if ( !"pom".equals( packaging ) )
360 {
361 File pom = pomFile;
362 if ( pom == null && generatePom )
363 {
364 pom = generatePomFile();
365 }
366 if ( pom != null )
367 {
368 if ( classifier == null )
369 {
370 ProjectArtifactMetadata metadata = new ProjectArtifactMetadata( artifact, pom );
371 artifact.addMetadata( metadata );
372 }
373 else
374 {
375 artifact.setFile( pom );
376 deployableArtifacts.add( artifact );
377 }
378 }
379 }
380
381 artifact.setRepository( deploymentRepository );
382
383 if ( sources != null )
384 {
385 projectHelper.attachArtifact( project, "jar", "sources", sources );
386 }
387
388 if ( javadoc != null )
389 {
390 projectHelper.attachArtifact( project, "jar", "javadoc", javadoc );
391 }
392
393 if ( files != null )
394 {
395 if ( types == null )
396 {
397 throw new MojoExecutionException( "You must specify 'types' if you specify 'files'" );
398 }
399 if ( classifiers == null )
400 {
401 throw new MojoExecutionException( "You must specify 'classifiers' if you specify 'files'" );
402 }
403 int filesLength = StringUtils.countMatches( files, "," );
404 int typesLength = StringUtils.countMatches( types, "," );
405 int classifiersLength = StringUtils.countMatches( classifiers, "," );
406 if ( typesLength != filesLength )
407 {
408 throw new MojoExecutionException( "You must specify the same number of entries in 'files' and "
409 + "'types' (respectively " + filesLength + " and " + typesLength + " entries )" );
410 }
411 if ( classifiersLength != filesLength )
412 {
413 throw new MojoExecutionException( "You must specify the same number of entries in 'files' and "
414 + "'classifiers' (respectively " + filesLength + " and " + classifiersLength + " entries )" );
415 }
416 int fi = 0;
417 int ti = 0;
418 int ci = 0;
419 for ( int i = 0; i <= filesLength; i++ )
420 {
421 int nfi = files.indexOf( ',', fi );
422 if ( nfi == -1 )
423 {
424 nfi = files.length();
425 }
426 int nti = types.indexOf( ',', ti );
427 if ( nti == -1 )
428 {
429 nti = types.length();
430 }
431 int nci = classifiers.indexOf( ',', ci );
432 if ( nci == -1 )
433 {
434 nci = classifiers.length();
435 }
436 File file = new File( files.substring( fi, nfi ) );
437 if ( !file.isFile() )
438 {
439
440 file = new File( project.getBasedir(), files.substring( fi, nfi ) );
441 }
442 if ( file.isFile() )
443 {
444 if ( StringUtils.isWhitespace( classifiers.substring( ci, nci ) ) )
445 {
446 projectHelper.attachArtifact( project, types.substring( ti, nti ).trim(), file );
447 }
448 else
449 {
450 projectHelper.attachArtifact( project, types.substring( ti, nti ).trim(),
451 classifiers.substring( ci, nci ).trim(), file );
452 }
453 }
454 else
455 {
456 throw new MojoExecutionException( "Specified side artifact " + file + " does not exist" );
457 }
458 fi = nfi + 1;
459 ti = nti + 1;
460 ci = nci + 1;
461 }
462 }
463 else
464 {
465 if ( types != null )
466 {
467 throw new MojoExecutionException( "You must specify 'files' if you specify 'types'" );
468 }
469 if ( classifiers != null )
470 {
471 throw new MojoExecutionException( "You must specify 'files' if you specify 'classifiers'" );
472 }
473 }
474
475 List<Artifact> attachedArtifacts = project.getAttachedArtifacts();
476
477 for ( Artifact attached : attachedArtifacts )
478 {
479 deployableArtifacts.add( attached );
480 }
481
482 try
483 {
484 artifactDeployer.deploy( getSession().getProjectBuildingRequest(), deploymentRepository,
485 deployableArtifacts );
486 }
487 catch ( ArtifactDeployerException e )
488 {
489 throw new MojoExecutionException( e.getMessage(), e );
490 }
491 }
492
493
494
495
496
497
498
499
500
501
502 private MavenProject createMavenProject()
503 throws MojoExecutionException, MojoFailureException
504 {
505 if ( groupId == null || artifactId == null || version == null || packaging == null )
506 {
507 throw new MojoExecutionException( "The artifact information is incomplete: 'groupId', 'artifactId', "
508 + "'version' and 'packaging' are required." );
509 }
510 ModelSource modelSource =
511 new StringModelSource( "<project>" + "<modelVersion>4.0.0</modelVersion>" + "<groupId>" + groupId
512 + "</groupId>" + "<artifactId>" + artifactId + "</artifactId>" + "<version>" + version + "</version>"
513 + "<packaging>" + ( classifier == null ? packaging : "pom" ) + "</packaging>" + "</project>" );
514 DefaultProjectBuildingRequest buildingRequest =
515 new DefaultProjectBuildingRequest( getSession().getProjectBuildingRequest() );
516 buildingRequest.setProcessPlugins( false );
517 try
518 {
519 return projectBuilder.build( modelSource, buildingRequest ).getProject();
520 }
521 catch ( ProjectBuildingException e )
522 {
523 if ( e.getCause() instanceof ModelBuildingException )
524 {
525 throw new MojoExecutionException( "The artifact information is not valid:" + Os.LINE_SEP
526 + e.getCause().getMessage() );
527 }
528 throw new MojoFailureException( "Unable to create the project.", e );
529 }
530 }
531
532
533
534
535
536
537
538 private File getLocalRepoFile()
539 {
540 DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate();
541 coordinate.setGroupId( groupId );
542 coordinate.setArtifactId( artifactId );
543 coordinate.setVersion( version );
544 coordinate.setClassifier( classifier );
545 coordinate.setExtension( packaging );
546 String path = repoManager.getPathForLocalArtifact( getSession().getProjectBuildingRequest(), coordinate );
547 return new File( repoManager.getLocalRepositoryBasedir( getSession().getProjectBuildingRequest() ), path );
548 }
549
550
551
552
553
554
555 private void processModel( Model model )
556 {
557 Parent parent = model.getParent();
558
559 if ( this.groupId == null )
560 {
561 this.groupId = model.getGroupId();
562 if ( this.groupId == null && parent != null )
563 {
564 this.groupId = parent.getGroupId();
565 }
566 }
567 if ( this.artifactId == null )
568 {
569 this.artifactId = model.getArtifactId();
570 }
571 if ( this.version == null )
572 {
573 this.version = model.getVersion();
574 if ( this.version == null && parent != null )
575 {
576 this.version = parent.getVersion();
577 }
578 }
579 if ( this.packaging == null )
580 {
581 this.packaging = model.getPackaging();
582 }
583 }
584
585
586
587
588
589
590
591
592 Model readModel( File pomFile )
593 throws MojoExecutionException
594 {
595 Reader reader = null;
596 try
597 {
598 reader = ReaderFactory.newXmlReader( pomFile );
599 final Model model = new MavenXpp3Reader().read( reader );
600 reader.close();
601 reader = null;
602 return model;
603 }
604 catch ( FileNotFoundException e )
605 {
606 throw new MojoExecutionException( "POM not found " + pomFile, e );
607 }
608 catch ( IOException e )
609 {
610 throw new MojoExecutionException( "Error reading POM " + pomFile, e );
611 }
612 catch ( XmlPullParserException e )
613 {
614 throw new MojoExecutionException( "Error parsing POM " + pomFile, e );
615 }
616 finally
617 {
618 IOUtil.close( reader );
619 }
620 }
621
622
623
624
625
626
627
628 private File generatePomFile()
629 throws MojoExecutionException
630 {
631 Model model = generateModel();
632
633 Writer fw = null;
634 try
635 {
636 File tempFile = File.createTempFile( "mvndeploy", ".pom" );
637 tempFile.deleteOnExit();
638
639 fw = WriterFactory.newXmlWriter( tempFile );
640
641 new MavenXpp3Writer().write( fw, model );
642
643 fw.close();
644 fw = null;
645
646 return tempFile;
647 }
648 catch ( IOException e )
649 {
650 throw new MojoExecutionException( "Error writing temporary pom file: " + e.getMessage(), e );
651 }
652 finally
653 {
654 IOUtil.close( fw );
655 }
656 }
657
658
659
660
661
662
663 private Model generateModel()
664 {
665 Model model = new Model();
666
667 model.setModelVersion( "4.0.0" );
668
669 model.setGroupId( groupId );
670 model.setArtifactId( artifactId );
671 model.setVersion( version );
672 model.setPackaging( packaging );
673
674 model.setDescription( description );
675
676 return model;
677 }
678
679 void setGroupId( String groupId )
680 {
681 this.groupId = groupId;
682 }
683
684 void setArtifactId( String artifactId )
685 {
686 this.artifactId = artifactId;
687 }
688
689 void setVersion( String version )
690 {
691 this.version = version;
692 }
693
694 void setPackaging( String packaging )
695 {
696 this.packaging = packaging;
697 }
698
699 void setPomFile( File pomFile )
700 {
701 this.pomFile = pomFile;
702 }
703
704 String getGroupId()
705 {
706 return groupId;
707 }
708
709 String getArtifactId()
710 {
711 return artifactId;
712 }
713
714 String getVersion()
715 {
716 return version;
717 }
718
719 String getPackaging()
720 {
721 return packaging;
722 }
723
724 File getFile()
725 {
726 return file;
727 }
728
729 String getClassifier()
730 {
731 return classifier;
732 }
733
734 void setClassifier( String classifier )
735 {
736 this.classifier = classifier;
737 }
738
739 }