View Javadoc
1   package org.apache.maven.plugin.install;
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 java.io.File;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.LinkedHashSet;
27  import java.util.List;
28  import java.util.concurrent.atomic.AtomicInteger;
29  
30  import org.apache.maven.artifact.Artifact;
31  import org.apache.maven.artifact.installer.ArtifactInstallationException;
32  import org.apache.maven.artifact.metadata.ArtifactMetadata;
33  import org.apache.maven.plugin.MojoExecutionException;
34  import org.apache.maven.plugins.annotations.LifecyclePhase;
35  import org.apache.maven.plugins.annotations.Mojo;
36  import org.apache.maven.plugins.annotations.Parameter;
37  import org.apache.maven.project.MavenProject;
38  import org.apache.maven.project.artifact.ProjectArtifactMetadata;
39  
40  /**
41   * Installs the project's main artifact, and any other artifacts attached by other plugins in the lifecycle, to the
42   * local repository.
43   * 
44   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
45   * @version $Id: InstallMojo.java 1617120 2014-08-10 15:15:48Z khmarbaise $
46   */
47  @Mojo( name = "install", defaultPhase = LifecyclePhase.INSTALL, threadSafe = true )
48  public class InstallMojo
49      extends AbstractInstallMojo
50  {
51  
52      /**
53       * When building with multiple threads, reaching the last project doesn't have to mean that all projects are ready
54       * to be installed
55       */
56      private static final AtomicInteger readyProjectsCounter = new AtomicInteger();
57  
58      private static final List<InstallRequest> installRequests =
59          Collections.synchronizedList( new ArrayList<InstallRequest>() );
60  
61      /**
62       */
63      @Parameter( defaultValue = "${project}", readonly = true, required = true )
64      private MavenProject project;
65  
66      @Parameter( defaultValue = "${reactorProjects}", required = true, readonly = true )
67      private List<MavenProject> reactorProjects;
68  
69      /**
70       * Whether every project should be installed during its own install-phase or at the end of the multimodule build. If
71       * set to {@code true} and the build fails, none of the reactor projects is installed. <strong>(experimental)</strong>
72       * 
73       * @since 2.5
74       */
75      @Parameter( defaultValue = "false", property = "installAtEnd" )
76      private boolean installAtEnd;
77  
78      /**
79       * @deprecated either use project.getPackaging() or reactorProjects.get(i).getPackaging()
80       */
81      @Parameter( defaultValue = "${project.packaging}", required = true, readonly = true )
82      protected String packaging;
83  
84      /**
85       * @deprecated either use project.getFile() or reactorProjects.get(i).getFile()
86       */
87      @Parameter( defaultValue = "${project.file}", required = true, readonly = true )
88      private File pomFile;
89  
90      /**
91       * Set this to <code>true</code> to bypass artifact installation. Use this for artifacts that does not need to be
92       * installed in the local repository.
93       * 
94       * @since 2.4
95       */
96      @Parameter( property = "maven.install.skip", defaultValue = "false" )
97      private boolean skip;
98  
99      /**
100      * @deprecated either use project.getArtifact() or reactorProjects.get(i).getArtifact()
101      */
102     @Parameter( defaultValue = "${project.artifact}", required = true, readonly = true )
103     private Artifact artifact;
104 
105     /**
106      * @deprecated either use project.getAttachedArtifacts() or reactorProjects.get(i).getAttachedArtifacts()
107      */
108     @Parameter( defaultValue = "${project.attachedArtifacts}", required = true, readonly = true )
109     private List<Artifact> attachedArtifacts;
110 
111     public void execute()
112         throws MojoExecutionException
113     {
114         boolean addedInstallRequest = false;
115         if ( skip )
116         {
117             getLog().info( "Skipping artifact installation" );
118         }
119         else
120         {
121             InstallRequest currentExecutionInstallRequest =
122                 new InstallRequest().setProject( project ).setCreateChecksum( createChecksum ).setUpdateReleaseInfo( updateReleaseInfo );
123 
124             if ( !installAtEnd )
125             {
126                 installProject( currentExecutionInstallRequest );
127             }
128             else
129             {
130                 installRequests.add( currentExecutionInstallRequest );
131                 addedInstallRequest = true;
132             }
133         }
134 
135         boolean projectsReady = readyProjectsCounter.incrementAndGet() == reactorProjects.size();
136         if ( projectsReady )
137         {
138             synchronized ( installRequests )
139             {
140                 while ( !installRequests.isEmpty() )
141                 {
142                     installProject( installRequests.remove( 0 ) );
143                 }
144             }
145         }
146         else if ( addedInstallRequest )
147         {
148             getLog().info( "Installing " + project.getGroupId() + ":" + project.getArtifactId() + ":"
149                                + project.getVersion() + " at end" );
150         }
151     }
152 
153     private void installProject( InstallRequest request )
154         throws MojoExecutionException
155     {
156         MavenProject project = request.getProject();
157         boolean createChecksum = request.isCreateChecksum();
158         boolean updateReleaseInfo = request.isUpdateReleaseInfo();
159 
160         Artifact artifact = project.getArtifact();
161         String packaging = project.getPackaging();
162         File pomFile = project.getFile();
163         @SuppressWarnings( "unchecked" )
164         List<Artifact> attachedArtifacts = project.getAttachedArtifacts();
165 
166         // TODO: push into transformation
167         boolean isPomArtifact = "pom".equals( packaging );
168 
169         ArtifactMetadata metadata;
170 
171         if ( updateReleaseInfo )
172         {
173             artifact.setRelease( true );
174         }
175 
176         try
177         {
178             Collection<File> metadataFiles = new LinkedHashSet<File>();
179 
180             if ( isPomArtifact )
181             {
182                 installer.install( pomFile, artifact, localRepository );
183                 installChecksums( artifact, createChecksum );
184                 addMetaDataFilesForArtifact( artifact, metadataFiles, createChecksum );
185             }
186             else
187             {
188                 metadata = new ProjectArtifactMetadata( artifact, pomFile );
189                 artifact.addMetadata( metadata );
190 
191                 File file = artifact.getFile();
192 
193                 // Here, we have a temporary solution to MINSTALL-3 (isDirectory() is true if it went through compile
194                 // but not package). We are designing in a proper solution for Maven 2.1
195                 if ( file != null && file.isFile() )
196                 {
197                     installer.install( file, artifact, localRepository );
198                     installChecksums( artifact, createChecksum );
199                     addMetaDataFilesForArtifact( artifact, metadataFiles, createChecksum );
200                 }
201                 else if ( !attachedArtifacts.isEmpty() )
202                 {
203                     getLog().info( "No primary artifact to install, installing attached artifacts instead." );
204 
205                     Artifact pomArtifact =
206                         artifactFactory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(),
207                                                                artifact.getBaseVersion() );
208                     pomArtifact.setFile( pomFile );
209                     if ( updateReleaseInfo )
210                     {
211                         pomArtifact.setRelease( true );
212                     }
213 
214                     installer.install( pomFile, pomArtifact, localRepository );
215                     installChecksums( pomArtifact, createChecksum );
216                     addMetaDataFilesForArtifact( pomArtifact, metadataFiles, createChecksum );
217                 }
218                 else
219                 {
220                     throw new MojoExecutionException(
221                                                       "The packaging for this project did not assign a file to the build artifact" );
222                 }
223             }
224 
225             for ( Artifact attached : attachedArtifacts )
226             {
227                 installer.install( attached.getFile(), attached, localRepository );
228                 installChecksums( attached, createChecksum );
229                 addMetaDataFilesForArtifact( attached, metadataFiles, createChecksum );
230             }
231 
232             installChecksums( metadataFiles );
233         }
234         catch ( ArtifactInstallationException e )
235         {
236             throw new MojoExecutionException( e.getMessage(), e );
237         }
238     }
239 
240     public void setSkip( boolean skip )
241     {
242         this.skip = skip;
243     }
244 
245 }