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