diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java index d413c3d94f..f75b23fe20 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java @@ -56,6 +56,8 @@ import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.Parameter; import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.lifecycle.Execution; +import org.apache.maven.plugin.lifecycle.Phase; import org.apache.maven.project.MavenProject; import org.apache.maven.repository.RepositorySystem; import org.apache.maven.wagon.ResourceDoesNotExistException; @@ -265,7 +267,10 @@ private void execute( MavenProject project, MavenSession session, MojoExecution } public MavenExecutionPlan calculateExecutionPlan( MavenSession session, String... tasks ) - throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException, PluginManagerException + throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, + CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException, + InvalidPluginDescriptorException, PluginManagerException, LifecyclePhaseNotFoundException, + LifecycleNotFoundException { MavenProject project = session.getCurrentProject(); @@ -306,7 +311,7 @@ public MavenExecutionPlan calculateExecutionPlan( MavenSession session, String.. populateMojoExecutionConfiguration( project, mojoExecution, false ); - calculateForkedExecutions( mojoExecution, project, new HashSet() ); + calculateForkedExecutions( mojoExecution, session, project, new HashSet() ); collectDependencyResolutionScopes( requiredDependencyResolutionScopes, mojoExecution ); } @@ -379,93 +384,93 @@ private void calculateExecutionForIndividualGoal( MavenSession session, List lifecyclePlan, String lifecyclePhase ) - throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException - { - MavenProject project = session.getCurrentProject(); - - // 1. - // - // Based on the lifecycle phase we are given, let's find the corresponding lifecycle. - // + private void calculateExecutionForLifecyclePhase( MavenSession session, List lifecyclePlan, + String lifecyclePhase ) + throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, + CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException, + InvalidPluginDescriptorException, LifecyclePhaseNotFoundException + { + Map> phaseToMojoMapping = calculateLifecycleMappings( session, lifecyclePhase ); + + for ( List mojoExecutions : phaseToMojoMapping.values() ) + { + lifecyclePlan.addAll( mojoExecutions ); + } + } + + private Map> calculateLifecycleMappings( MavenSession session, String lifecyclePhase ) + throws LifecyclePhaseNotFoundException, PluginNotFoundException, PluginResolutionException, + PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException, + InvalidPluginDescriptorException + { + /* + * Determine the lifecycle that corresponds to the given phase. + */ + Lifecycle lifecycle = phaseToLifecycleMap.get( lifecyclePhase ); - // 2. - // - // If we are dealing with the "clean" or "site" lifecycle then there are currently no lifecycle mappings but there are default phases - // that need to be run instead. - // - // Now we need to take into account the packaging type of the project. For a project of type WAR, the lifecycle where mojos are mapped - // on to the given phases in the lifecycle are going to be a little different then, say, a project of type JAR. - // - - // 3. - // - // Once we have the lifecycle mapping for the given packaging, we need to know whats phases we need to worry about executing. - // - - // Create an ordered Map of the phases in the lifecycle to a list of mojos to execute. - Map> phaseToMojoMapping = new LinkedHashMap>(); - - // 4. - - //TODO: need to separate the lifecycles - if ( lifecycle == null ) { - logger.info( "Invalid task '" - + lifecyclePhase - + "' : you must specify a valid lifecycle phase, or a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal" ); - throw new MojoNotFoundException( lifecyclePhase, null ); + logger.info( "Invalid task '" + lifecyclePhase + "' : you must specify a valid lifecycle phase" + + ", or a goal in the format : or" + + " :::" ); + throw new LifecyclePhaseNotFoundException( lifecyclePhase ); } - + + /* + * Initialize mapping from lifecycle phase to bound mojos. The key set of this map denotes the phases the caller + * is interested in, i.e. all phases up to and including the specified phase. + */ + + Map> lifecycleMappings = new LinkedHashMap>(); + for ( String phase : lifecycle.getPhases() ) { - List mojos = new ArrayList(); + List mojoExecutions = new ArrayList(); - //TODO: remove hard coding + // TODO: remove hard coding if ( phase.equals( "clean" ) ) { Plugin plugin = new Plugin(); plugin.setGroupId( "org.apache.maven.plugins" ); plugin.setArtifactId( "maven-clean-plugin" ); plugin.setVersion( "2.3" ); - mojos.add( new MojoExecution( plugin, "clean", "default-clean" ) ); + mojoExecutions.add( new MojoExecution( plugin, "clean", "default-clean" ) ); } - // This is just just laying out the initial structure of the mojos to run in each phase of the - // lifecycle. Everything is now done in the project builder correctly so this could likely - // go away shortly. We no longer need to pull out bits from the default lifecycle. The MavenProject - // comes to us intact as it should. + lifecycleMappings.put( phase, mojoExecutions ); - phaseToMojoMapping.put( phase, mojos ); + if ( phase.equals( lifecyclePhase ) ) + { + break; + } } - // 5. Just build up the list of mojos that will execute for every phase. - // - // This will be useful for having the complete build plan and then we can filter/optimize later. - // + /* + * Grab plugin executions that are bound to the selected lifecycle phases from project. The effective model of + * the project already contains the plugin executions induced by the project's packaging type. Remember, all + * phases of interest and only those are in the lifecyle mapping, if a phase has no value in the map, we are not + * interested in any of the executions bound to it. + */ + + MavenProject project = session.getCurrentProject(); + for ( Plugin plugin : project.getBuild().getPlugins() ) { for ( PluginExecution execution : plugin.getExecutions() ) { // if the phase is specified then I don't have to go fetch the plugin yet and pull it down - // to examine the phase it is associated to. + // to examine the phase it is associated to. if ( execution.getPhase() != null ) { - for ( String goal : execution.getGoals() ) + List mojoExecutions = lifecycleMappings.get( execution.getPhase() ); + if ( mojoExecutions != null ) { - if ( phaseToMojoMapping.get( execution.getPhase() ) == null ) + for ( String goal : execution.getGoals() ) { - // This is happening because executions in the POM are getting mixed into the clean lifecycle - // So for the lifecycle mapping we need a map with the phases as keys so we can easily check - // if this phase belongs to the given lifecycle. this shows the system is messed up. this - // shouldn't happen. - phaseToMojoMapping.put( execution.getPhase(), new ArrayList() ); + MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() ); + mojoExecutions.add( mojoExecution ); } - - MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() ); - phaseToMojoMapping.get( execution.getPhase() ).add( mojoExecution ); } } // if not then i need to grab the mojo descriptor and look at the phase that is specified @@ -473,37 +478,29 @@ private void calculateExecutionForLifecyclePhase( MavenSession session, List mojoExecutions = lifecycleMappings.get( mojoDescriptor.getPhase() ); + if ( mojoExecutions != null ) { MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() ); - phaseToMojoMapping.get( mojoDescriptor.getPhase() ).add( mojoExecution ); + mojoExecutions.add( mojoExecution ); } } } } } - // 6. - // - // We are only interested in the phases that correspond to the lifecycle we are trying to run. If we are running the "clean" - // lifecycle we are not interested in goals -- like "generate-sources -- that belong to the default lifecycle. - // - for ( String phase : phaseToMojoMapping.keySet() ) - { - lifecyclePlan.addAll( phaseToMojoMapping.get( phase ) ); + return lifecycleMappings; + } - if ( phase.equals( lifecyclePhase ) ) - { - break; - } - } - } - - private void calculateForkedExecutions( MojoExecution mojoExecution, MavenProject project, + private void calculateForkedExecutions( MojoExecution mojoExecution, MavenSession session, MavenProject project, Collection alreadyForkedExecutions ) - throws MojoNotFoundException + throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException, + PluginDescriptorParsingException, CycleDetectedInPluginGraphException, NoPluginFoundForPrefixException, + InvalidPluginDescriptorException, LifecyclePhaseNotFoundException, LifecycleNotFoundException { MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); @@ -516,8 +513,115 @@ private void calculateForkedExecutions( MojoExecution mojoExecution, MavenProjec if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) ) { - // TODO + String forkedPhase = mojoDescriptor.getExecutePhase(); + Map> lifecycleMappings = calculateLifecycleMappings( session, forkedPhase ); + + for ( List forkedExecutions : lifecycleMappings.values() ) + { + for ( MojoExecution forkedExecution : forkedExecutions ) + { + if ( forkedExecution.getMojoDescriptor() == null ) + { + MojoDescriptor forkedMojoDescriptor = + pluginManager.getMojoDescriptor( forkedExecution.getPlugin(), forkedExecution.getGoal(), + session.getLocalRepository(), + project.getPluginArtifactRepositories() ); + + forkedExecution.setMojoDescriptor( forkedMojoDescriptor ); + } + + populateMojoExecutionConfiguration( project, forkedExecution, false ); + } + } + + String forkedLifecycle = mojoDescriptor.getExecuteLifecycle(); + + if ( StringUtils.isNotEmpty( forkedLifecycle ) ) + { + org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay; + + try + { + lifecycleOverlay = pluginDescriptor.getLifecycleMapping( forkedLifecycle ); + } + catch ( IOException e ) + { + throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), e ); + } + catch ( XmlPullParserException e ) + { + throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), e ); + } + + if ( lifecycleOverlay == null ) + { + throw new LifecycleNotFoundException( forkedLifecycle ); + } + + for ( Phase phase : lifecycleOverlay.getPhases() ) + { + List forkedExecutions = lifecycleMappings.get( phase.getId() ); + if ( forkedExecutions != null ) + { + for ( Execution execution : phase.getExecutions() ) + { + for ( String goal : execution.getGoals() ) + { + MojoDescriptor forkedMojoDescriptor; + + if ( goal.indexOf( ':' ) < 0 ) + { + forkedMojoDescriptor = pluginDescriptor.getMojo( goal ); + if ( forkedMojoDescriptor == null ) + { + throw new MojoNotFoundException( goal, pluginDescriptor ); + } + } + else + { + forkedMojoDescriptor = getMojoDescriptor( goal, session ); + } + + MojoExecution forkedExecution = + new MojoExecution( forkedMojoDescriptor, mojoExecution.getExecutionId() ); + + Xpp3Dom forkedConfiguration = (Xpp3Dom) execution.getConfiguration(); + + forkedExecution.setConfiguration( forkedConfiguration ); + + populateMojoExecutionConfiguration( project, forkedExecution, true ); + + forkedExecutions.add( forkedExecution ); + } + } + + Xpp3Dom phaseConfiguration = (Xpp3Dom) phase.getConfiguration(); + if ( phaseConfiguration != null ) + { + for ( MojoExecution forkedExecution : forkedExecutions ) + { + Xpp3Dom executionConfiguration = forkedExecution.getConfiguration(); + + Xpp3Dom mergedConfiguration = + Xpp3Dom.mergeXpp3Dom( phaseConfiguration, executionConfiguration ); + + forkedExecution.setConfiguration( mergedConfiguration ); + } + } + } + } + } + + for ( List forkedExecutions : lifecycleMappings.values() ) + { + for ( MojoExecution forkedExecution : forkedExecutions ) + { + calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions ); + + mojoExecution.addForkedExecution( forkedExecution ); + } + } } else if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteGoal() ) ) { @@ -533,7 +637,7 @@ else if ( StringUtils.isNotEmpty( mojoDescriptor.getExecuteGoal() ) ) populateMojoExecutionConfiguration( project, forkedExecution, true ); - calculateForkedExecutions( forkedExecution, project, alreadyForkedExecutions ); + calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions ); mojoExecution.addForkedExecution( forkedExecution ); } @@ -555,7 +659,7 @@ private void populateMojoExecutionConfiguration( MavenProject project, MojoExecu Plugin plugin = project.getPlugin( g + ":" + a ); - if ( plugin != null ) + if ( plugin != null && StringUtils.isNotEmpty( mojoExecution.getExecutionId() ) ) { for ( PluginExecution e : plugin.getExecutions() ) { @@ -565,7 +669,10 @@ private void populateMojoExecutionConfiguration( MavenProject project, MojoExecu Xpp3Dom mojoConfiguration = extractMojoConfiguration( executionConfiguration, mojoExecution.getMojoDescriptor() ); - mojoExecution.setConfiguration( mojoConfiguration ); + Xpp3Dom mergedConfiguration = + Xpp3Dom.mergeXpp3Dom( mojoExecution.getConfiguration(), mojoConfiguration ); + + mojoExecution.setConfiguration( mergedConfiguration ); return; } @@ -576,18 +683,20 @@ private void populateMojoExecutionConfiguration( MavenProject project, MojoExecu { Xpp3Dom defaultDom = convert( mojoExecution.getMojoDescriptor() ); + Xpp3Dom mojoDom = defaultDom; + if ( plugin != null && plugin.getConfiguration() != null ) { Xpp3Dom projectDom = (Xpp3Dom) plugin.getConfiguration(); projectDom = extractMojoConfiguration( projectDom, mojoExecution.getMojoDescriptor() ); - mojoExecution.setConfiguration( Xpp3Dom.mergeXpp3Dom( projectDom, defaultDom, Boolean.TRUE ) ); - } - else - { - mojoExecution.setConfiguration( defaultDom ); + mojoDom = Xpp3Dom.mergeXpp3Dom( projectDom, defaultDom, Boolean.TRUE ); } + + mojoDom = Xpp3Dom.mergeXpp3Dom( mojoExecution.getConfiguration(), mojoDom ); + + mojoExecution.setConfiguration( mojoDom ); } - } + } /** * Extracts the configuration for a single mojo from the specified execution configuration by discarding any @@ -699,7 +808,7 @@ else if ( numTokens == 3 ) plugin.setArtifactId( tok.nextToken() ); goal = tok.nextToken(); } - if ( numTokens == 2 ) + else if ( numTokens == 2 ) { // We have a prefix and goal // diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleExecutor.java index 4fcea84604..e3da7cead1 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleExecutor.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleExecutor.java @@ -49,7 +49,10 @@ public interface LifecycleExecutor * @throws LifecycleExecutionException */ MavenExecutionPlan calculateExecutionPlan( MavenSession session, String... tasks ) - throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException, PluginManagerException; + throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, + CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException, + InvalidPluginDescriptorException, PluginManagerException, LifecyclePhaseNotFoundException, + LifecycleNotFoundException; // For a given project packaging find all the plugins that are bound to any registered // lifecycles. The project builder needs to now what default plugin information needs to be diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleNotFoundException.java b/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleNotFoundException.java new file mode 100644 index 0000000000..d79eaa13d0 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/LifecycleNotFoundException.java @@ -0,0 +1,54 @@ +package org.apache.maven.lifecycle; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Signals a failure to locate a lifecycle. + * + * @author Benjamin Bentmann + */ +public class LifecycleNotFoundException + extends Exception +{ + + private final String lifecycleId; + + /** + * Creates a new exception to indicate that the specified lifecycle is unknown. + * + * @param lifecycleId The identifier of the lifecycle that could not be located, may be {@code null}. + */ + public LifecycleNotFoundException( String lifecycleId ) + { + super( "Unknown lifecycle " + lifecycleId ); + this.lifecycleId = ( lifecycleId != null ) ? lifecycleId : ""; + } + + /** + * Gets the identifier of the lifecycle that was not found. + * + * @return The identifier of the lifecycle that was not found, never {@code null}. + */ + public String getLifecycleId() + { + return lifecycleId; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/LifecyclePhaseNotFoundException.java b/maven-core/src/main/java/org/apache/maven/lifecycle/LifecyclePhaseNotFoundException.java new file mode 100644 index 0000000000..383ac55086 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/LifecyclePhaseNotFoundException.java @@ -0,0 +1,54 @@ +package org.apache.maven.lifecycle; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Signals a failure to locate the lifecycle for some phase. + * + * @author Benjamin Bentmann + */ +public class LifecyclePhaseNotFoundException + extends Exception +{ + + private final String lifecyclePhase; + + /** + * Creates a new exception to indicate that the specified lifecycle phase is not defined by any known lifecycle. + * + * @param lifecyclePhase The name of the lifecycle phase that could not be located, may be {@code null}. + */ + public LifecyclePhaseNotFoundException( String lifecyclePhase ) + { + super( "Unknown lifecycle phase " + lifecyclePhase ); + this.lifecyclePhase = ( lifecyclePhase != null ) ? lifecyclePhase : ""; + } + + /** + * Gets the lifecycle phase that was not found. + * + * @return The lifecycle phase that was not found, never {@code null}. + */ + public String getLifecyclePhase() + { + return lifecyclePhase; + } + +} diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java index 7698e15e33..2e96e886b2 100644 --- a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java @@ -19,7 +19,15 @@ * under the License. */ +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.MalformedURLException; +import java.net.URL; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -28,8 +36,14 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.lifecycle.Lifecycle; +import org.apache.maven.plugin.lifecycle.LifecycleConfiguration; +import org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Reader; import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.component.repository.ComponentSetDescriptor; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; /** * @author Jason van Zyl @@ -37,6 +51,9 @@ public class PluginDescriptor extends ComponentSetDescriptor { + + private static final String LIFECYCLE_DESCRIPTOR = "META-INF/maven/lifecycle.xml"; + private String groupId; private String artifactId; @@ -49,14 +66,14 @@ public class PluginDescriptor private boolean inheritedByDefault = true; - private List artifacts; + private List artifacts; private ClassRealm classRealm; // calculated on-demand. - private Map artifactMap; + private Map artifactMap; - private Set introducedDependencyArtifacts; + private Set introducedDependencyArtifacts; private String name; @@ -66,6 +83,8 @@ public class PluginDescriptor private Artifact pluginArtifact; + private Map lifecycleMappings; + // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- @@ -208,12 +227,12 @@ public void setInheritedByDefault( boolean inheritedByDefault ) this.inheritedByDefault = inheritedByDefault; } - public List getArtifacts() + public List getArtifacts() { return artifacts; } - public void setArtifacts( List artifacts ) + public void setArtifacts( List artifacts ) { this.artifacts = artifacts; @@ -221,7 +240,7 @@ public void setArtifacts( List artifacts ) artifactMap = null; } - public Map getArtifactMap() + public Map getArtifactMap() { if ( artifactMap == null ) { @@ -280,14 +299,15 @@ public ClassRealm getClassRealm() return classRealm; } - public void setIntroducedDependencyArtifacts( Set introducedDependencyArtifacts ) + public void setIntroducedDependencyArtifacts( Set introducedDependencyArtifacts ) { this.introducedDependencyArtifacts = introducedDependencyArtifacts; } - public Set getIntroducedDependencyArtifacts() + public Set getIntroducedDependencyArtifacts() { - return introducedDependencyArtifacts != null ? introducedDependencyArtifacts : Collections.EMPTY_SET; + return ( introducedDependencyArtifacts != null ) ? introducedDependencyArtifacts + : Collections. emptySet(); } public void setName( String name ) @@ -329,4 +349,61 @@ public void setPluginArtifact( Artifact pluginArtifact ) { this.pluginArtifact = pluginArtifact; } + + public Lifecycle getLifecycleMapping( String lifecycleId ) + throws IOException, XmlPullParserException + { + if ( lifecycleMappings == null ) + { + LifecycleConfiguration lifecycleConfiguration; + + Reader reader = null; + try + { + reader = ReaderFactory.newXmlReader( getDescriptorStream( LIFECYCLE_DESCRIPTOR ) ); + + lifecycleConfiguration = new LifecycleMappingsXpp3Reader().read( reader ); + } + finally + { + IOUtil.close( reader ); + } + + lifecycleMappings = new HashMap(); + + for ( Lifecycle lifecycle : lifecycleConfiguration.getLifecycles() ) + { + lifecycleMappings.put( lifecycle.getId(), lifecycle ); + } + } + + return lifecycleMappings.get( lifecycleId ); + } + + private InputStream getDescriptorStream( String descriptor ) + throws IOException + { + File pluginFile = ( pluginArtifact != null ) ? pluginArtifact.getFile() : null; + if ( pluginFile == null ) + { + throw new IllegalStateException( "plugin main artifact has not been resolved" ); + } + + if ( pluginFile.isFile() ) + { + try + { + return new URL( "jar:" + pluginFile.toURI() + "!/" + descriptor ).openStream(); + } + catch ( MalformedURLException e ) + { + throw new IllegalStateException( e ); + } + } + else + { + return new FileInputStream( new File( pluginFile, descriptor ) ); + } + } + }