View Javadoc

1   package org.apache.maven.plugin.deploy;
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.artifact.Artifact;
23  import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
24  import org.apache.maven.artifact.metadata.ArtifactMetadata;
25  import org.apache.maven.artifact.repository.ArtifactRepository;
26  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
27  import org.apache.maven.model.Model;
28  import org.apache.maven.model.Parent;
29  import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
30  import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
31  import org.apache.maven.plugin.MojoExecutionException;
32  import org.apache.maven.plugin.MojoFailureException;
33  import org.apache.maven.project.MavenProject;
34  import org.apache.maven.project.MavenProjectHelper;
35  import org.apache.maven.project.artifact.ProjectArtifactMetadata;
36  import org.apache.maven.project.validation.ModelValidationResult;
37  import org.apache.maven.project.validation.ModelValidator;
38  import org.codehaus.plexus.util.FileUtils;
39  import org.codehaus.plexus.util.IOUtil;
40  import org.codehaus.plexus.util.ReaderFactory;
41  import org.codehaus.plexus.util.StringUtils;
42  import org.codehaus.plexus.util.WriterFactory;
43  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
44  
45  import java.io.File;
46  import java.io.FileNotFoundException;
47  import java.io.IOException;
48  import java.io.Reader;
49  import java.io.Writer;
50  import java.util.Iterator;
51  import java.util.List;
52  
53  /**
54   * Installs the artifact in the remote repository.
55   *
56   * @author <a href="mailto:aramirez@apache.org">Allan Ramirez</a>
57   * @goal deploy-file
58   * @requiresProject false
59   */
60  public class DeployFileMojo
61      extends AbstractDeployMojo
62  {
63      /**
64       * The default Maven project created when building the plugin
65       * 
66       * @parameter default-value="${project}"
67       * @required
68       * @readonly
69       */
70      private MavenProject project;
71  
72      /**
73       * Used for attaching the source and javadoc jars to the project.
74       *
75       * @component
76       */
77      private MavenProjectHelper projectHelper;
78  
79      /**
80       * GroupId of the artifact to be deployed.  Retrieved from POM file if specified.
81       *
82       * @parameter expression="${groupId}"
83       */
84      private String groupId;
85  
86      /**
87       * ArtifactId of the artifact to be deployed.  Retrieved from POM file if specified.
88       *
89       * @parameter expression="${artifactId}"
90       */
91      private String artifactId;
92  
93      /**
94       * Version of the artifact to be deployed.  Retrieved from POM file if specified.
95       *
96       * @parameter expression="${version}"
97       */
98      private String version;
99  
100     /**
101      * Type of the artifact to be deployed.  Retrieved from POM file if specified.
102      * Defaults to file extension if not specified via command line or POM.
103      *
104      * @parameter expression="${packaging}"
105      */
106     private String packaging;
107 
108     /**
109      * Description passed to a generated POM file (in case of generatePom=true)
110      *
111      * @parameter expression="${generatePom.description}"
112      */
113     private String description;
114 
115     /**
116      * File to be deployed.
117      *
118      * @parameter expression="${file}"
119      * @required
120      */
121     private File file;
122 
123     /**
124      * The bundled API docs for the artifact.
125      *
126      * @parameter expression="${javadoc}"
127      * @since 2.6
128      */
129     private File javadoc;
130 
131     /**
132      * The bundled sources for the artifact.
133      *
134      * @parameter expression="${sources}"
135      * @since 2.6
136      */
137     private File sources;
138 
139     /**
140      * Server Id to map on the &lt;id&gt; under &lt;server&gt; section of settings.xml
141      * In most cases, this parameter will be required for authentication.
142      *
143      * @parameter expression="${repositoryId}" default-value="remote-repository"
144      * @required
145      */
146     private String repositoryId;
147 
148     /**
149      * The type of remote repository layout to deploy to. Try <i>legacy</i> for 
150      * a Maven 1.x-style repository layout.
151      * 
152      * @parameter expression="${repositoryLayout}" default-value="default"
153      */
154     private String repositoryLayout;
155 
156     /**
157      * URL where the artifact will be deployed. <br/>
158      * ie ( file:///C:/m2-repo or scp://host.com/path/to/repo )
159      *
160      * @parameter expression="${url}"
161      * @required
162      */
163     private String url;
164 
165     /**
166      * Location of an existing POM file to be deployed alongside the main
167      * artifact, given by the ${file} parameter.
168      * 
169      * @parameter expression="${pomFile}"
170      */
171     private File pomFile;
172 
173     /**
174      * Upload a POM for this artifact.  Will generate a default POM if none is
175      * supplied with the pomFile argument.
176      *
177      * @parameter expression="${generatePom}" default-value="true"
178      */
179     private boolean generatePom;
180 
181     /**
182      * Add classifier to the artifact
183      *
184      * @parameter expression="${classifier}";
185      */
186     private String classifier;
187 
188     /**
189      * Whether to deploy snapshots with a unique version or not.
190      *
191      * @parameter expression="${uniqueVersion}" default-value="true"
192      */
193     private boolean uniqueVersion;
194 
195     /**
196      * The component used to validate the user-supplied artifact coordinates.
197      * 
198      * @component
199      */
200     private ModelValidator modelValidator;
201 
202     void initProperties()
203         throws MojoExecutionException
204     {
205         // Process the supplied POM (if there is one)
206         if ( pomFile != null )
207         {
208             generatePom = false;
209 
210             Model model = readModel( pomFile );
211 
212             processModel( model );
213         }
214         
215         if ( packaging == null && file != null )
216         {
217             packaging = FileUtils.getExtension( file.getName() );
218         }
219     }
220 
221     public void execute()
222         throws MojoExecutionException, MojoFailureException
223     {
224         failIfOffline();
225 
226         if ( !file.exists() )
227         {
228             throw new MojoExecutionException( file.getPath() + " not found." );
229         }
230 
231         initProperties();
232 
233         validateArtifactInformation();
234 
235         ArtifactRepositoryLayout layout = getLayout( repositoryLayout );
236 
237         ArtifactRepository deploymentRepository =
238             repositoryFactory.createDeploymentArtifactRepository( repositoryId, url, layout, uniqueVersion );
239 
240         String protocol = deploymentRepository.getProtocol();
241 
242         if ( StringUtils.isEmpty( protocol ) )
243         {
244             throw new MojoExecutionException( "No transfer protocol found." );
245         }
246 
247         // Create the artifact
248         Artifact artifact =
249             artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, packaging, classifier );
250 
251         if ( file.equals( getLocalRepoFile( artifact ) ) )
252         {
253             throw new MojoFailureException( "Cannot deploy artifact from the local repository: " + file );
254         }
255 
256         // Upload the POM if requested, generating one if need be
257         if ( !"pom".equals( packaging ) )
258         {
259             if ( pomFile != null )
260             {
261                 ArtifactMetadata metadata = new ProjectArtifactMetadata( artifact, pomFile );
262                 artifact.addMetadata( metadata );
263             }
264             else if ( generatePom )
265             {
266                 ArtifactMetadata metadata = new ProjectArtifactMetadata( artifact, generatePomFile() );
267                 artifact.addMetadata( metadata );
268             }
269         }
270 
271         if ( updateReleaseInfo )
272         {
273             artifact.setRelease( true );
274         }
275         
276         project.setArtifact( artifact );
277 
278         try
279         {
280             getDeployer().deploy( file, artifact, deploymentRepository, getLocalRepository() );
281         }
282         catch ( ArtifactDeploymentException e )
283         {
284             throw new MojoExecutionException( e.getMessage(), e );
285         }
286 
287         if ( sources != null )
288         {
289             projectHelper.attachArtifact( project, "jar", "sources", sources );
290         }
291 
292         if ( javadoc != null )
293         {
294             projectHelper.attachArtifact( project, "jar", "javadoc", javadoc );
295         }
296 
297         List attachedArtifacts = project.getAttachedArtifacts();
298 
299         for ( Iterator i = attachedArtifacts.iterator(); i.hasNext(); )
300         {
301             Artifact attached = ( Artifact ) i.next();
302 
303             try
304             {
305                 getDeployer().deploy( attached.getFile(), attached, deploymentRepository, getLocalRepository() );
306             }
307             catch ( ArtifactDeploymentException e )
308             {
309                 throw new MojoExecutionException( "Error deploying attached artifact " + attached.getFile() + ": " + e.getMessage(), e );
310             }
311         }
312 
313     }
314 
315     /**
316      * Gets the path of the specified artifact within the local repository. Note that the returned path need not exist
317      * (yet).
318      * 
319      * @param artifact The artifact whose local repo path should be determined, must not be <code>null</code>.
320      * @return The absolute path to the artifact when installed, never <code>null</code>.
321      */
322     private File getLocalRepoFile( Artifact artifact )
323     {
324         String path = getLocalRepository().pathOf( artifact );
325         return new File( getLocalRepository().getBasedir(), path );
326     }
327 
328     /**
329      * Process the supplied pomFile to get groupId, artifactId, version, and packaging
330      *
331      * @param model The POM to extract missing artifact coordinates from, must not be <code>null</code>.
332      */
333     private void processModel( Model model )
334     {
335         Parent parent = model.getParent();
336 
337         if ( this.groupId == null )
338         {
339             this.groupId = model.getGroupId();
340             if ( this.groupId == null && parent != null )
341             {
342                 this.groupId = parent.getGroupId();
343             }
344         }
345         if ( this.artifactId == null )
346         {
347             this.artifactId = model.getArtifactId();
348         }
349         if ( this.version == null )
350         {
351             this.version = model.getVersion();
352             if ( this.version == null && parent != null )
353             {
354                 this.version = parent.getVersion();
355             }
356         }
357         if ( this.packaging == null )
358         {
359             this.packaging = model.getPackaging();
360         }
361     }
362 
363     /**
364      * Extract the model from the specified POM file.
365      * 
366      * @param pomFile The path of the POM file to parse, must not be <code>null</code>.
367      * @return The model from the POM file, never <code>null</code>.
368      * @throws MojoExecutionException If the file doesn't exist of cannot be read.
369      */
370     Model readModel( File pomFile )
371         throws MojoExecutionException
372     {
373         Reader reader = null;
374         try
375         {
376             reader = ReaderFactory.newXmlReader( pomFile );
377             return new MavenXpp3Reader().read( reader );
378         }
379         catch ( FileNotFoundException e )
380         {
381             throw new MojoExecutionException( "POM not found " + pomFile, e );
382         }
383         catch ( IOException e )
384         {
385             throw new MojoExecutionException( "Error reading POM " + pomFile, e );
386         }
387         catch ( XmlPullParserException e )
388         {
389             throw new MojoExecutionException( "Error parsing POM " + pomFile, e );
390         }
391         finally
392         {
393             IOUtil.close( reader );
394         }
395     }
396 
397     private File generatePomFile()
398         throws MojoExecutionException
399     {
400         Model model = generateModel();
401 
402         Writer fw = null;
403         try
404         {
405             File tempFile = File.createTempFile( "mvndeploy", ".pom" );
406             tempFile.deleteOnExit();
407 
408             fw = WriterFactory.newXmlWriter( tempFile );
409             new MavenXpp3Writer().write( fw, model );
410 
411             return tempFile;
412         }
413         catch ( IOException e )
414         {
415             throw new MojoExecutionException( "Error writing temporary pom file: " + e.getMessage(), e );
416         }
417         finally
418         {
419             IOUtil.close( fw );
420         }
421     }
422 
423     /**
424      * Validates the user-supplied artifact information.
425      * 
426      * @throws MojoExecutionException If any artifact coordinate is invalid.
427      */
428     private void validateArtifactInformation()
429         throws MojoExecutionException
430     {
431         Model model = generateModel();
432 
433         ModelValidationResult result = modelValidator.validate( model );
434 
435         if ( result.getMessageCount() > 0 )
436         {
437             throw new MojoExecutionException( "The artifact information is incomplete or not valid:\n"
438                 + result.render( "  " ) );
439         }
440     }
441 
442     /**
443      * Generates a minimal model from the user-supplied artifact information.
444      * 
445      * @return The generated model, never <code>null</code>.
446      */
447     private Model generateModel()
448     {
449         Model model = new Model();
450 
451         model.setModelVersion( "4.0.0" );
452 
453         model.setGroupId( groupId );
454         model.setArtifactId( artifactId );
455         model.setVersion( version );
456         model.setPackaging( packaging );
457 
458         model.setDescription( description );
459 
460         return model;
461     }
462 
463     void setGroupId( String groupId )
464     {
465         this.groupId = groupId;
466     }
467 
468     void setArtifactId( String artifactId )
469     {
470         this.artifactId = artifactId;
471     }
472 
473     void setVersion( String version )
474     {
475         this.version = version;
476     }
477 
478     void setPackaging( String packaging )
479     {
480         this.packaging = packaging;
481     }
482 
483     void setPomFile( File pomFile )
484     {
485         this.pomFile = pomFile;
486     }
487 
488     String getGroupId()
489     {
490         return groupId;
491     }
492 
493     String getArtifactId()
494     {
495         return artifactId;
496     }
497 
498     String getVersion()
499     {
500         return version;
501     }
502 
503     String getPackaging()
504     {
505         return packaging;
506     }
507 
508     File getFile()
509     {
510         return file;
511     }
512 
513     String getClassifier()
514     {
515         return classifier;
516     }
517 
518     void setClassifier( String classifier )
519     {
520         this.classifier = classifier;
521     }
522 }