1 package org.apache.maven.continuum.release.phase;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
65
66
67
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 }