View Javadoc

1   package org.apache.maven.continuum.release.phase;
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.commons.cli.CommandLine;
23  import org.apache.commons.cli.CommandLineParser;
24  import org.apache.commons.cli.GnuParser;
25  import org.apache.commons.cli.OptionBuilder;
26  import org.apache.commons.cli.Options;
27  import org.apache.commons.cli.ParseException;
28  import org.apache.maven.artifact.repository.ArtifactRepository;
29  import org.apache.maven.artifact.repository.DefaultArtifactRepository;
30  import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
31  import org.apache.maven.continuum.release.ContinuumReleaseException;
32  import org.apache.maven.profiles.DefaultProfileManager;
33  import org.apache.maven.profiles.ProfileManager;
34  import org.apache.maven.project.DuplicateProjectException;
35  import org.apache.maven.project.MavenProject;
36  import org.apache.maven.project.MavenProjectBuilder;
37  import org.apache.maven.project.ProjectBuildingException;
38  import org.apache.maven.project.ProjectSorter;
39  import org.apache.maven.settings.MavenSettingsBuilder;
40  import org.apache.maven.settings.Settings;
41  import org.apache.maven.shared.release.ReleaseExecutionException;
42  import org.apache.maven.shared.release.ReleaseFailureException;
43  import org.apache.maven.shared.release.ReleaseResult;
44  import org.apache.maven.shared.release.config.ReleaseDescriptor;
45  import org.apache.maven.shared.release.env.ReleaseEnvironment;
46  import org.apache.maven.shared.release.phase.AbstractReleasePhase;
47  import org.codehaus.plexus.PlexusConstants;
48  import org.codehaus.plexus.PlexusContainer;
49  import org.codehaus.plexus.context.Context;
50  import org.codehaus.plexus.context.ContextException;
51  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
52  import org.codehaus.plexus.util.StringUtils;
53  import org.codehaus.plexus.util.dag.CycleDetectedException;
54  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
55  
56  import java.io.File;
57  import java.io.IOException;
58  import java.util.ArrayList;
59  import java.util.List;
60  import java.util.Properties;
61  import java.util.StringTokenizer;
62  
63  /**
64   * Generate the reactor projects
65   *
66   * @author Edwin Punzalan
67   * @version $Id: GenerateReactorProjectsPhase.java 1372260 2012-08-13 04:29:09Z brett $
68   */
69  public class GenerateReactorProjectsPhase
70      extends AbstractReleasePhase
71      implements Contextualizable
72  {
73      private MavenProjectBuilder projectBuilder;
74  
75      private MavenSettingsBuilder settingsBuilder;
76  
77      private PlexusContainer container;
78  
79      private static final char SET_SYSTEM_PROPERTY = 'D';
80  
81      private static final char ACTIVATE_PROFILES = 'P';
82  
83      public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
84          throws ReleaseExecutionException, ReleaseFailureException
85      {
86          ReleaseResult result = new ReleaseResult();
87  
88          try
89          {
90              reactorProjects.addAll( getReactorProjects( releaseDescriptor ) );
91          }
92          catch ( ContinuumReleaseException e )
93          {
94              throw new ReleaseExecutionException( "Unable to get reactor projects: " + e.getMessage(), e );
95          }
96  
97          result.setResultCode( ReleaseResult.SUCCESS );
98  
99          return result;
100     }
101 
102     public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
103         throws ReleaseExecutionException, ReleaseFailureException
104     {
105         return execute( releaseDescriptor, settings, reactorProjects );
106     }
107 
108 
109     public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
110                                   List reactorProjects )
111         throws ReleaseExecutionException, ReleaseFailureException
112     {
113         return execute( releaseDescriptor, releaseEnvironment.getSettings(), reactorProjects );
114     }
115 
116     public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
117                                    List reactorProjects )
118         throws ReleaseExecutionException, ReleaseFailureException
119     {
120         return execute( releaseDescriptor, releaseEnvironment.getSettings(), reactorProjects );
121     }
122 
123     private List getReactorProjects( ReleaseDescriptor descriptor )
124         throws ContinuumReleaseException
125     {
126         List<MavenProject> reactorProjects = new ArrayList<MavenProject>();
127 
128         MavenProject project;
129         try
130         {
131             String arguments = descriptor.getAdditionalArguments();
132             ArtifactRepository repository = getLocalRepository( arguments );
133             ProfileManager profileManager = getProfileManager( getSettings() );
134 
135             if ( arguments != null )
136             {
137                 activateProfiles( arguments, profileManager );
138             }
139 
140             project = projectBuilder.build( getProjectDescriptorFile( descriptor ), repository, profileManager );
141 
142             reactorProjects.add( project );
143 
144             addModules( reactorProjects, project, repository );
145         }
146         catch ( ParseException e )
147         {
148             throw new ContinuumReleaseException( "Unable to parse arguments.", e );
149         }
150         catch ( ProjectBuildingException e )
151         {
152             throw new ContinuumReleaseException( "Failed to build project.", e );
153         }
154 
155         try
156         {
157             reactorProjects = new ProjectSorter( reactorProjects ).getSortedProjects();
158         }
159         catch ( CycleDetectedException e )
160         {
161             throw new ContinuumReleaseException( "Failed to sort projects.", e );
162         }
163         catch ( DuplicateProjectException e )
164         {
165             throw new ContinuumReleaseException( "Failed to sort projects.", e );
166         }
167 
168         return reactorProjects;
169     }
170 
171     private void addModules( List<MavenProject> reactorProjects, MavenProject project, ArtifactRepository repository )
172         throws ContinuumReleaseException
173     {
174         for ( Object o : project.getModules() )
175         {
176             String moduleDir = StringUtils.replace( o.toString(), '\\', '/' );
177 
178             File pomFile = new File( project.getBasedir(), moduleDir + "/pom.xml" );
179 
180             try
181             {
182                 MavenProject reactorProject = projectBuilder.build( pomFile, repository, getProfileManager(
183                     getSettings() ) );
184 
185                 reactorProjects.add( reactorProject );
186 
187                 addModules( reactorProjects, reactorProject, repository );
188             }
189             catch ( ProjectBuildingException e )
190             {
191                 throw new ContinuumReleaseException( "Failed to build project.", e );
192             }
193         }
194     }
195 
196     private File getProjectDescriptorFile( ReleaseDescriptor descriptor )
197     {
198         String parentPath = descriptor.getWorkingDirectory();
199 
200         String pomFilename = descriptor.getPomFileName();
201         if ( pomFilename == null )
202         {
203             pomFilename = "pom.xml";
204         }
205 
206         return new File( parentPath, pomFilename );
207     }
208 
209     private ArtifactRepository getLocalRepository( String arguments )
210         throws ContinuumReleaseException
211     {
212         String localRepository = null;
213         boolean found = false;
214 
215         if ( arguments != null )
216         {
217             String[] args = arguments.split( " " );
218 
219             for ( String arg : args )
220             {
221                 if ( arg.contains( "-Dmaven.repo.local=" ) )
222                 {
223                     localRepository = arg.substring( arg.indexOf( "=" ) + 1 );
224 
225                     if ( localRepository.endsWith( "\"" ) )
226                     {
227                         localRepository = localRepository.substring( 0, localRepository.indexOf( "\"" ) );
228                         break;
229                     }
230 
231                     found = true;
232                     continue;
233                 }
234 
235                 if ( found )
236                 {
237                     localRepository += " " + arg;
238 
239                     if ( localRepository.endsWith( "\"" ) )
240                     {
241                         localRepository = localRepository.substring( 0, localRepository.indexOf( "\"" ) );
242                         break;
243                     }
244                 }
245             }
246         }
247 
248         if ( localRepository == null )
249         {
250             localRepository = getSettings().getLocalRepository();
251         }
252 
253         return new DefaultArtifactRepository( "local-repository", "file://" + localRepository,
254                                               new DefaultRepositoryLayout() );
255     }
256 
257     private ProfileManager getProfileManager( Settings settings )
258     {
259         Properties props = new Properties();
260         return new DefaultProfileManager( container, settings, props );
261     }
262 
263     private Settings getSettings()
264         throws ContinuumReleaseException
265     {
266         try
267         {
268             return settingsBuilder.buildSettings();
269         }
270         catch ( IOException e )
271         {
272             throw new ContinuumReleaseException( "Failed to get Maven Settings.", e );
273         }
274         catch ( XmlPullParserException e )
275         {
276             throw new ContinuumReleaseException( "Failed to get Maven Settings.", e );
277         }
278     }
279 
280     @SuppressWarnings( "static-access" )
281     private void activateProfiles( String arguments, ProfileManager profileManager )
282         throws ParseException
283     {
284         CommandLineParser parser = new GnuParser();
285 
286         Options options = new Options();
287 
288         options.addOption( OptionBuilder.withLongOpt( "activate-profiles" ).withDescription(
289             "Comma-delimited list of profiles to activate" ).hasArg().create( ACTIVATE_PROFILES ) );
290 
291         options.addOption( OptionBuilder.withLongOpt( "define" ).hasArg().withDescription(
292             "Define a system property" ).create( SET_SYSTEM_PROPERTY ) );
293 
294         String[] args = StringUtils.split( arguments );
295 
296         CommandLine commandLine = parser.parse( options, args );
297 
298         if ( commandLine.hasOption( ACTIVATE_PROFILES ) )
299         {
300             String[] profileOptionValues = commandLine.getOptionValues( ACTIVATE_PROFILES );
301 
302             if ( profileOptionValues != null )
303             {
304                 for ( int i = 0; i < profileOptionValues.length; ++i )
305                 {
306                     StringTokenizer profileTokens = new StringTokenizer( profileOptionValues[i], "," );
307 
308                     while ( profileTokens.hasMoreTokens() )
309                     {
310                         String profileAction = profileTokens.nextToken().trim();
311 
312                         if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
313                         {
314                             profileManager.explicitlyDeactivate( profileAction.substring( 1 ) );
315                         }
316                         else if ( profileAction.startsWith( "+" ) )
317                         {
318                             profileManager.explicitlyActivate( profileAction.substring( 1 ) );
319                         }
320                         else
321                         {
322                             profileManager.explicitlyActivate( profileAction );
323                         }
324                     }
325                 }
326             }
327         }
328     }
329 
330     public void contextualize( Context context )
331         throws ContextException
332     {
333         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
334     }
335 
336 
337 }