From db64a6a1fd6f51f0d9c1be7a47deb1cdd58b8f9b Mon Sep 17 00:00:00 2001 From: Jason van Zyl Date: Thu, 6 Sep 2007 00:44:55 +0000 Subject: [PATCH] o adding plugin-descriptor to start creating a single artifact which represents a plugin runtime git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@573123 13f79535-47bb-0310-9956-ffa450edef68 --- maven-plugin-api/pom.xml | 12 + .../DuplicateMojoDescriptorException.java | 31 ++ .../DuplicateParameterException.java | 31 ++ .../descriptor/InvalidParameterException.java | 39 ++ .../InvalidPluginDescriptorException.java | 38 ++ .../plugin/descriptor/MojoDescriptor.java | 455 ++++++++++++++++++ .../maven/plugin/descriptor/Parameter.java | 190 ++++++++ .../plugin/descriptor/PluginDescriptor.java | 362 ++++++++++++++ .../descriptor/PluginDescriptorBuilder.java | 341 +++++++++++++ .../maven/plugin/descriptor/Requirement.java | 55 +++ maven-plugin-api/src/main/mdo/lifecycle.mdo | 125 +++++ .../lifecycle/LifecycleXpp3ReaderTest.java | 57 +++ .../src/test/resources/lifecycle.xml | 39 ++ 13 files changed, 1775 insertions(+) create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/DuplicateMojoDescriptorException.java create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/DuplicateParameterException.java create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/InvalidParameterException.java create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/InvalidPluginDescriptorException.java create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/Parameter.java create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/Requirement.java create mode 100644 maven-plugin-api/src/main/mdo/lifecycle.mdo create mode 100644 maven-plugin-api/src/test/java/org/apache/maven/plugin/lifecycle/LifecycleXpp3ReaderTest.java create mode 100644 maven-plugin-api/src/test/resources/lifecycle.xml diff --git a/maven-plugin-api/pom.xml b/maven-plugin-api/pom.xml index e81dc04077..fa0eafcebd 100644 --- a/maven-plugin-api/pom.xml +++ b/maven-plugin-api/pom.xml @@ -37,4 +37,16 @@ under the License. test + + + + org.codehaus.modello + modello-maven-plugin + + src/main/mdo/lifecycle.mdo + 1.0.0 + + + + diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/DuplicateMojoDescriptorException.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/DuplicateMojoDescriptorException.java new file mode 100644 index 0000000000..26aeb9533e --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/DuplicateMojoDescriptorException.java @@ -0,0 +1,31 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +public class DuplicateMojoDescriptorException + extends InvalidPluginDescriptorException +{ + + public DuplicateMojoDescriptorException( String goalPrefix, String goal, String existingImplementation, String newImplementation ) + { + super( "Goal: " + goal + " already exists in the plugin descriptor for prefix: " + goalPrefix + "\nExisting implementation is: " + existingImplementation + "\nConflicting implementation is: " + newImplementation ); + } + +} diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/DuplicateParameterException.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/DuplicateParameterException.java new file mode 100644 index 0000000000..4cad9b7c01 --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/DuplicateParameterException.java @@ -0,0 +1,31 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +public class DuplicateParameterException + extends InvalidPluginDescriptorException +{ + + public DuplicateParameterException( String message ) + { + super( message ); + } + +} diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/InvalidParameterException.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/InvalidParameterException.java new file mode 100644 index 0000000000..9988436e4a --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/InvalidParameterException.java @@ -0,0 +1,39 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +/** + * @author Jason van Zyl + * @version $Id: InvalidParameterException.java,v 1.1 2005/02/20 16:25:21 + * jdcasey Exp $ + */ +public class InvalidParameterException + extends InvalidPluginDescriptorException +{ + public InvalidParameterException( String element, int i ) + { + super( "The " + element + " element in parameter # " + i + " is invalid. It cannot be null." ); + } + + public InvalidParameterException( String message, Throwable cause ) + { + super( message, cause ); + } +} \ No newline at end of file diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/InvalidPluginDescriptorException.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/InvalidPluginDescriptorException.java new file mode 100644 index 0000000000..4b8e739772 --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/InvalidPluginDescriptorException.java @@ -0,0 +1,38 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +import org.codehaus.plexus.configuration.PlexusConfigurationException; + +public class InvalidPluginDescriptorException + extends PlexusConfigurationException +{ + + public InvalidPluginDescriptorException( String message, Throwable cause ) + { + super( message, cause ); + } + + public InvalidPluginDescriptorException( String message ) + { + super( message ); + } + +} diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java new file mode 100644 index 0000000000..1620ec6873 --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java @@ -0,0 +1,455 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +import org.apache.maven.plugin.Mojo; +import org.codehaus.plexus.component.repository.ComponentDescriptor; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * The bean containing the mojo descriptor. + * + * @todo is there a need for the delegation of MavenMojoDescriptor to this? Why not just extend ComponentDescriptor here? + */ +public class MojoDescriptor + extends ComponentDescriptor + implements Cloneable +{ + public static String MAVEN_PLUGIN = "maven-plugin"; + + public static final String SINGLE_PASS_EXEC_STRATEGY = "once-per-session"; + + public static final String MULTI_PASS_EXEC_STRATEGY = "always"; + + private static final String DEFAULT_INSTANTIATION_STRATEGY = "per-lookup"; + + private static final String DEFAULT_LANGUAGE = "java"; + + private List parameters; + + private Map parameterMap; + + private String executionStrategy = SINGLE_PASS_EXEC_STRATEGY; + + private String goal; + + private String phase; + + private String since; + + private String executePhase; + + private String executeGoal; + + private String executeLifecycle; + + private String deprecated; + + private boolean aggregator = false; + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + private String dependencyResolutionRequired = null; + + private boolean projectRequired = true; + + private boolean onlineRequired = false; + + private PlexusConfiguration mojoConfiguration; + + private PluginDescriptor pluginDescriptor; + + private boolean inheritedByDefault = true; + + private boolean directInvocationOnly = false; + + private boolean requiresReports = false; + + public MojoDescriptor() + { + setInstantiationStrategy( DEFAULT_INSTANTIATION_STRATEGY ); + setComponentFactory( DEFAULT_LANGUAGE ); + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + public String getLanguage() + { + return getComponentFactory(); + } + + public void setLanguage( String language ) + { + setComponentFactory( language ); + } + + public String getDeprecated() + { + return deprecated; + } + + public void setDeprecated( String deprecated ) + { + this.deprecated = deprecated; + } + + public List getParameters() + { + return parameters; + } + + public void setParameters( List parameters ) + throws DuplicateParameterException + { + for ( Iterator it = parameters.iterator(); it.hasNext(); ) + { + Parameter parameter = (Parameter) it.next(); + addParameter( parameter ); + } + } + + public void addParameter( Parameter parameter ) + throws DuplicateParameterException + { + if ( parameters != null && parameters.contains( parameter ) ) + { + throw new DuplicateParameterException( parameter.getName() + + " has been declared multiple times in mojo with goal: " + getGoal() + " (implementation: " + + getImplementation() + ")" ); + } + else + { + if ( parameters == null ) + { + parameters = new LinkedList(); + } + + parameters.add( parameter ); + } + } + + public Map getParameterMap() + { + if ( parameterMap == null ) + { + parameterMap = new HashMap(); + + if ( parameters != null ) + { + for ( Iterator iterator = parameters.iterator(); iterator.hasNext(); ) + { + Parameter pd = (Parameter) iterator.next(); + + parameterMap.put( pd.getName(), pd ); + } + } + } + + return parameterMap; + } + + // ---------------------------------------------------------------------- + // Dependency requirement + // ---------------------------------------------------------------------- + + public void setDependencyResolutionRequired( String requiresDependencyResolution ) + { + this.dependencyResolutionRequired = requiresDependencyResolution; + } + + public String isDependencyResolutionRequired() + { + return dependencyResolutionRequired; + } + + // ---------------------------------------------------------------------- + // Project requirement + // ---------------------------------------------------------------------- + + public void setProjectRequired( boolean requiresProject ) + { + this.projectRequired = requiresProject; + } + + public boolean isProjectRequired() + { + return projectRequired; + } + + // ---------------------------------------------------------------------- + // Online vs. Offline requirement + // ---------------------------------------------------------------------- + + public void setOnlineRequired( boolean requiresOnline ) + { + this.onlineRequired = requiresOnline; + } + + // blech! this isn't even intelligible as a method name. provided for + // consistency... + public boolean isOnlineRequired() + { + return onlineRequired; + } + + // more english-friendly method...keep the code clean! :) + public boolean requiresOnline() + { + return onlineRequired; + } + + public String getPhase() + { + return phase; + } + + public void setPhase( String phase ) + { + this.phase = phase; + } + + public String getSince() + { + return since; + } + + public void setSince( String since ) + { + this.since = since; + } + + public String getGoal() + { + return goal; + } + + public void setGoal( String goal ) + { + this.goal = goal; + } + + public String getExecutePhase() + { + return executePhase; + } + + public void setExecutePhase( String executePhase ) + { + this.executePhase = executePhase; + } + + public boolean alwaysExecute() + { + return MULTI_PASS_EXEC_STRATEGY.equals( executionStrategy ); + } + + public String getExecutionStrategy() + { + return executionStrategy; + } + + public void setExecutionStrategy( String executionStrategy ) + { + this.executionStrategy = executionStrategy; + } + + public PlexusConfiguration getMojoConfiguration() + { + if ( mojoConfiguration == null ) + { + mojoConfiguration = new XmlPlexusConfiguration( "configuration" ); + } + return mojoConfiguration; + } + + public void setMojoConfiguration( PlexusConfiguration mojoConfiguration ) + { + this.mojoConfiguration = mojoConfiguration; + } + + public String getRole() + { + return Mojo.ROLE; + } + + public String getRoleHint() + { + return getId(); + } + + public String getId() + { + return getPluginDescriptor().getId() + ":" + getGoal(); + } + + public String getFullGoalName() + { + return getPluginDescriptor().getGoalPrefix() + ":" + getGoal(); + } + + public String getComponentType() + { + return MAVEN_PLUGIN; + } + + public PluginDescriptor getPluginDescriptor() + { + return pluginDescriptor; + } + + public void setPluginDescriptor( PluginDescriptor pluginDescriptor ) + { + this.pluginDescriptor = pluginDescriptor; + } + + public boolean isInheritedByDefault() + { + return inheritedByDefault; + } + + public void setInheritedByDefault( boolean inheritedByDefault ) + { + this.inheritedByDefault = inheritedByDefault; + } + + public boolean equals( Object object ) + { + if ( this == object ) + { + return true; + } + + if ( object instanceof MojoDescriptor ) + { + MojoDescriptor other = (MojoDescriptor) object; + + if ( !compareObjects( getPluginDescriptor(), other.getPluginDescriptor() ) ) + { + return false; + } + + if ( !compareObjects( getGoal(), other.getGoal() ) ) + { + return false; + } + + return true; + } + + return false; + } + + private boolean compareObjects( Object first, Object second ) + { + if ( ( first == null && second != null ) || ( first != null && second == null ) ) + { + return false; + } + + if ( !first.equals( second ) ) + { + return false; + } + + return true; + } + + public int hashCode() + { + int result = 1; + + String goal = getGoal(); + + if ( goal != null ) + { + result += goal.hashCode(); + } + + PluginDescriptor pd = getPluginDescriptor(); + + if ( pd != null ) + { + result -= pd.hashCode(); + } + + return result; + } + + public String getExecuteLifecycle() + { + return executeLifecycle; + } + + public void setExecuteLifecycle( String executeLifecycle ) + { + this.executeLifecycle = executeLifecycle; + } + + public void setAggregator( boolean aggregator ) + { + this.aggregator = aggregator; + } + + public boolean isAggregator() + { + return aggregator; + } + + public boolean isDirectInvocationOnly() + { + return directInvocationOnly; + } + + public void setDirectInvocationOnly( boolean directInvocationOnly ) + { + this.directInvocationOnly = directInvocationOnly; + } + + public boolean isRequiresReports() + { + return requiresReports; + } + + public void setRequiresReports( boolean requiresReports ) + { + this.requiresReports = requiresReports; + } + + public void setExecuteGoal( String executeGoal ) + { + this.executeGoal = executeGoal; + } + + public String getExecuteGoal() + { + return executeGoal; + } +} diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/Parameter.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/Parameter.java new file mode 100644 index 0000000000..ecb61f2cf0 --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/Parameter.java @@ -0,0 +1,190 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +/** + * @author Jason van Zyl + * @version $Id$ + */ +public class Parameter +{ + private String alias; + + private String name; + + private String type; + + private boolean required; + + private boolean editable = true; + + private String description; + + private String expression; + + private String deprecated; + + private String defaultValue; + + private String implementation; + + private Requirement requirement; + + private String since; + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + public String getName() + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + public String getType() + { + return type; + } + + public void setType( String type ) + { + this.type = type; + } + + public boolean isRequired() + { + return required; + } + + public void setRequired( boolean required ) + { + this.required = required; + } + + public String getDescription() + { + return description; + } + + public void setDescription( String description ) + { + this.description = description; + } + + public String getExpression() + { + return expression; + } + + public void setExpression( String expression ) + { + this.expression = expression; + } + + public String getDeprecated() + { + return deprecated; + } + + public void setDeprecated( String deprecated ) + { + this.deprecated = deprecated; + } + + public int hashCode() + { + return name.hashCode(); + } + + public boolean equals( Object other ) + { + return ( other instanceof Parameter ) && getName().equals( ( (Parameter) other ).getName() ); + } + + public String getAlias() + { + return alias; + } + + public void setAlias( String alias ) + { + this.alias = alias; + } + + public boolean isEditable() + { + return editable; + } + + public void setEditable( boolean editable ) + { + this.editable = editable; + } + + public void setDefaultValue( String defaultValue ) + { + this.defaultValue = defaultValue; + } + + public String getDefaultValue() + { + return defaultValue; + } + + public String toString() + { + return "Mojo parameter [name: \'" + getName() + "\'; alias: \'" + getAlias() + "\']"; + } + + public Requirement getRequirement() + { + return requirement; + } + + public void setRequirement( Requirement requirement ) + { + this.requirement = requirement; + } + + public String getImplementation() + { + return implementation; + } + + public void setImplementation( String implementation ) + { + this.implementation = implementation; + } + + public String getSince() + { + return since; + } + + public void setSince( String since ) + { + this.since = since; + } +} 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 new file mode 100644 index 0000000000..3663b1a0bb --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java @@ -0,0 +1,362 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.ArtifactUtils; +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.xml.pull.XmlPullParserException; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Jason van Zyl + * @version $Id$ + */ +public class PluginDescriptor + extends ComponentSetDescriptor +{ + private String groupId; + + private String artifactId; + + private String version; + + private String goalPrefix; + + private String source; + + private boolean inheritedByDefault = true; + + private List artifacts; + + private Map lifecycleMappings; + + private ClassRealm classRealm; + + // calculated on-demand. + private Map artifactMap; + + private Set introducedDependencyArtifacts; + + private String name; + + private String description; + + private Artifact pluginArtifact; + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + public List getMojos() + { + return getComponents(); + } + + public void addMojo( MojoDescriptor mojoDescriptor ) + throws DuplicateMojoDescriptorException + { + MojoDescriptor existing = null; + // this relies heavily on the equals() and hashCode() for ComponentDescriptor, + // which uses role:roleHint for identity...and roleHint == goalPrefix:goal. + // role does not vary for Mojos. + List mojos = getComponents(); + + if ( mojos != null && mojos.contains( mojoDescriptor ) ) + { + int indexOf = mojos.indexOf( mojoDescriptor ); + + existing = (MojoDescriptor) mojos.get( indexOf ); + } + + if ( existing != null ) + { + throw new DuplicateMojoDescriptorException( getGoalPrefix(), mojoDescriptor.getGoal(), existing + .getImplementation(), mojoDescriptor.getImplementation() ); + } + else + { + addComponentDescriptor( mojoDescriptor ); + } + } + + public String getGroupId() + { + return groupId; + } + + public void setGroupId( String groupId ) + { + this.groupId = groupId; + } + + public String getArtifactId() + { + return artifactId; + } + + public void setArtifactId( String artifactId ) + { + this.artifactId = artifactId; + } + + // ---------------------------------------------------------------------- + // Dependencies + // ---------------------------------------------------------------------- + + public static String constructPluginKey( String groupId, String artifactId, String version ) + { + return groupId + ":" + artifactId + ":" + version; + } + + public String getPluginLookupKey() + { + return groupId + ":" + artifactId; + } + + public String getId() + { + return constructPluginKey( groupId, artifactId, version ); + } + + public static String getDefaultPluginArtifactId( String id ) + { + return "maven-" + id + "-plugin"; + } + + public static String getDefaultPluginGroupId() + { + return "org.apache.maven.plugins"; + } + + /** + * Parse maven-...-plugin. + * + * @todo move to plugin-tools-api as a default only + */ + public static String getGoalPrefixFromArtifactId( String artifactId ) + { + if ( "maven-plugin-plugin".equals( artifactId ) ) + { + return "plugin"; + } + else + { + return artifactId.replaceAll( "-?maven-?", "" ).replaceAll( "-?plugin-?", "" ); + } + } + + public String getGoalPrefix() + { + return goalPrefix; + } + + public void setGoalPrefix( String goalPrefix ) + { + this.goalPrefix = goalPrefix; + } + + public void setVersion( String version ) + { + this.version = version; + } + + public String getVersion() + { + return version; + } + + public void setSource( String source ) + { + this.source = source; + } + + public String getSource() + { + return source; + } + + public boolean isInheritedByDefault() + { + return inheritedByDefault; + } + + public void setInheritedByDefault( boolean inheritedByDefault ) + { + this.inheritedByDefault = inheritedByDefault; + } + + public List getArtifacts() + { + return artifacts; + } + + public void setArtifacts( List artifacts ) + { + this.artifacts = artifacts; + + // clear the calculated artifactMap + artifactMap = null; + } + + public Map getArtifactMap() + { + if ( artifactMap == null ) + { + artifactMap = ArtifactUtils.artifactMapByVersionlessId( getArtifacts() ); + } + + return artifactMap; + } + + public boolean equals( Object object ) + { + if ( this == object ) + { + return true; + } + + return getId().equals( ( (PluginDescriptor) object ).getId() ); + } + + public int hashCode() + { + return 10 + getId().hashCode(); + } + + public MojoDescriptor getMojo( String goal ) + { + // TODO: could we use a map? Maybe if the parent did that for components too, as this is too vulnerable to + // changes above not being propogated to the map + + MojoDescriptor mojoDescriptor = null; + for ( Iterator i = getMojos().iterator(); i.hasNext() && mojoDescriptor == null; ) + { + MojoDescriptor desc = (MojoDescriptor) i.next(); + if ( goal.equals( desc.getGoal() ) ) + { + mojoDescriptor = desc; + } + } + return mojoDescriptor; + } + + public Lifecycle getLifecycleMapping( String lifecycle ) + throws IOException, XmlPullParserException + { + if ( lifecycleMappings == null ) + { + LifecycleMappingsXpp3Reader reader = new LifecycleMappingsXpp3Reader(); + InputStreamReader r = null; + LifecycleConfiguration config; + + try + { + InputStream resourceAsStream = classRealm.getResourceAsStream( "/META-INF/maven/lifecycle.xml" ); + if ( resourceAsStream == null ) + { + throw new FileNotFoundException( "Unable to find /META-INF/maven/lifecycle.xml in the plugin" ); + } + r = new InputStreamReader( resourceAsStream ); + config = reader.read( r, true ); + } + finally + { + IOUtil.close( r ); + } + + Map map = new HashMap(); + + for ( Iterator i = config.getLifecycles().iterator(); i.hasNext(); ) + { + Lifecycle l = (Lifecycle) i.next(); + map.put( l.getId(), l ); + } + + lifecycleMappings = map; + } + return (Lifecycle) lifecycleMappings.get( lifecycle ); + } + + public void setClassRealm( ClassRealm classRealm ) + { + this.classRealm = classRealm; + } + + public ClassRealm getClassRealm() + { + return classRealm; + } + + public void setIntroducedDependencyArtifacts( Set introducedDependencyArtifacts ) + { + this.introducedDependencyArtifacts = introducedDependencyArtifacts; + } + + public Set getIntroducedDependencyArtifacts() + { + return introducedDependencyArtifacts != null ? introducedDependencyArtifacts : Collections.EMPTY_SET; + } + + public void setName( String name ) + { + this.name = name; + } + + public String getName() + { + return name; + } + + public void setDescription( String description ) + { + this.description = description; + } + + public String getDescription() + { + return description; + } + + public Artifact getPluginArtifact() + { + return pluginArtifact; + } + + public void setPluginArtifact( Artifact pluginArtifact ) + { + this.pluginArtifact = pluginArtifact; + } +} diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java new file mode 100644 index 0000000000..dec99a6710 --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java @@ -0,0 +1,341 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.component.repository.ComponentRequirement; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.codehaus.plexus.configuration.PlexusConfigurationException; +import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Jason van Zyl + * @version $Id$ + */ +public class PluginDescriptorBuilder +{ + public PluginDescriptor build( Reader reader ) + throws PlexusConfigurationException + { + return build( reader, null ); + } + + public PluginDescriptor build( Reader reader, String source ) + throws PlexusConfigurationException + { + PlexusConfiguration c = buildConfiguration( reader ); + + PluginDescriptor pluginDescriptor = new PluginDescriptor(); + + pluginDescriptor.setSource( source ); + pluginDescriptor.setGroupId( c.getChild( "groupId" ).getValue() ); + pluginDescriptor.setArtifactId( c.getChild( "artifactId" ).getValue() ); + pluginDescriptor.setVersion( c.getChild( "version" ).getValue() ); + pluginDescriptor.setGoalPrefix( c.getChild( "goalPrefix" ).getValue() ); + + pluginDescriptor.setName( c.getChild( "name" ).getValue() ); + pluginDescriptor.setDescription( c.getChild( "description" ).getValue() ); + + String isolatedRealm = c.getChild( "isolatedRealm" ).getValue(); + + if ( isolatedRealm != null ) + { + pluginDescriptor.setIsolatedRealm( Boolean.valueOf( isolatedRealm ).booleanValue() ); + } + + String inheritedByDefault = c.getChild( "inheritedByDefault" ).getValue(); + + if ( inheritedByDefault != null ) + { + pluginDescriptor.setInheritedByDefault( Boolean.valueOf( inheritedByDefault ).booleanValue() ); + } + + // ---------------------------------------------------------------------- + // Components + // ---------------------------------------------------------------------- + + PlexusConfiguration[] mojoConfigurations = c.getChild( "mojos" ).getChildren( "mojo" ); + + for ( int i = 0; i < mojoConfigurations.length; i++ ) + { + PlexusConfiguration component = mojoConfigurations[i]; + + MojoDescriptor mojoDescriptor = buildComponentDescriptor( component, pluginDescriptor ); + + pluginDescriptor.addMojo( mojoDescriptor ); + } + + // ---------------------------------------------------------------------- + // Dependencies + // ---------------------------------------------------------------------- + + PlexusConfiguration[] dependencyConfigurations = c.getChild( "dependencies" ).getChildren( "dependency" ); + + List dependencies = new ArrayList(); + + for ( int i = 0; i < dependencyConfigurations.length; i++ ) + { + PlexusConfiguration d = dependencyConfigurations[i]; + + ComponentDependency cd = new ComponentDependency(); + + cd.setArtifactId( d.getChild( "artifactId" ).getValue() ); + + cd.setGroupId( d.getChild( "groupId" ).getValue() ); + + cd.setType( d.getChild( "type" ).getValue() ); + + cd.setVersion( d.getChild( "version" ).getValue() ); + + dependencies.add( cd ); + } + + pluginDescriptor.setDependencies( dependencies ); + + return pluginDescriptor; + } + + public MojoDescriptor buildComponentDescriptor( PlexusConfiguration c, PluginDescriptor pluginDescriptor ) + throws PlexusConfigurationException + { + MojoDescriptor mojo = new MojoDescriptor(); + mojo.setPluginDescriptor( pluginDescriptor ); + + mojo.setGoal( c.getChild( "goal" ).getValue() ); + + mojo.setImplementation( c.getChild( "implementation" ).getValue() ); + + PlexusConfiguration langConfig = c.getChild( "language" ); + + if ( langConfig != null ) + { + mojo.setLanguage( langConfig.getValue() ); + } + + PlexusConfiguration configuratorConfig = c.getChild( "configurator" ); + + if ( configuratorConfig != null ) + { + mojo.setComponentConfigurator( configuratorConfig.getValue() ); + } + + PlexusConfiguration composerConfig = c.getChild( "composer" ); + + if ( composerConfig != null ) + { + mojo.setComponentComposer( composerConfig.getValue() ); + } + + String since = c.getChild( "since" ).getValue(); + + if ( since != null ) + { + mojo.setSince( since ); + } + + String phase = c.getChild( "phase" ).getValue(); + + if ( phase != null ) + { + mojo.setPhase( phase ); + } + + String executePhase = c.getChild( "executePhase" ).getValue(); + + if ( executePhase != null ) + { + mojo.setExecutePhase( executePhase ); + } + + String executeMojo = c.getChild( "executeGoal" ).getValue(); + + if ( executeMojo != null ) + { + mojo.setExecuteGoal( executeMojo ); + } + + String executeLifecycle = c.getChild( "executeLifecycle" ).getValue(); + + if ( executeLifecycle != null ) + { + mojo.setExecuteLifecycle( executeLifecycle ); + } + + mojo.setInstantiationStrategy( c.getChild( "instantiationStrategy" ).getValue() ); + + mojo.setDescription( c.getChild( "description" ).getValue() ); + + String dependencyResolution = c.getChild( "requiresDependencyResolution" ).getValue(); + + if ( dependencyResolution != null ) + { + mojo.setDependencyResolutionRequired( dependencyResolution ); + } + + String directInvocationOnly = c.getChild( "requiresDirectInvocation" ).getValue(); + + if ( directInvocationOnly != null ) + { + mojo.setDirectInvocationOnly( Boolean.valueOf( directInvocationOnly ).booleanValue() ); + } + + String requiresProject = c.getChild( "requiresProject" ).getValue(); + + if ( requiresProject != null ) + { + mojo.setProjectRequired( Boolean.valueOf( requiresProject ).booleanValue() ); + } + + String requiresReports = c.getChild( "requiresReports" ).getValue(); + + if ( requiresReports != null ) + { + mojo.setRequiresReports( Boolean.valueOf( requiresReports ).booleanValue() ); + } + + String aggregator = c.getChild( "aggregator" ).getValue(); + + if ( aggregator != null ) + { + mojo.setAggregator( Boolean.valueOf( aggregator ).booleanValue() ); + } + + String requiresOnline = c.getChild( "requiresOnline" ).getValue(); + + if ( requiresOnline != null ) + { + mojo.setOnlineRequired( Boolean.valueOf( requiresOnline ).booleanValue() ); + } + + String inheritedByDefault = c.getChild( "inheritedByDefault" ).getValue(); + + if ( inheritedByDefault != null ) + { + mojo.setInheritedByDefault( Boolean.valueOf( inheritedByDefault ).booleanValue() ); + } + + // ---------------------------------------------------------------------- + // Parameters + // ---------------------------------------------------------------------- + + PlexusConfiguration[] parameterConfigurations = c.getChild( "parameters" ).getChildren( "parameter" ); + + List parameters = new ArrayList(); + + for ( int i = 0; i < parameterConfigurations.length; i++ ) + { + PlexusConfiguration d = parameterConfigurations[i]; + + Parameter parameter = new Parameter(); + + parameter.setName( d.getChild( "name" ).getValue() ); + + parameter.setAlias( d.getChild( "alias" ).getValue() ); + + parameter.setType( d.getChild( "type" ).getValue() ); + + String required = d.getChild( "required" ).getValue(); + + parameter.setRequired( Boolean.valueOf( required ).booleanValue() ); + + PlexusConfiguration editableConfig = d.getChild( "editable" ); + + // we need the null check for pre-build legacy plugins... + if ( editableConfig != null ) + { + String editable = d.getChild( "editable" ).getValue(); + + parameter.setEditable( editable == null || Boolean.valueOf( editable ).booleanValue() ); + } + + parameter.setDescription( d.getChild( "description" ).getValue() ); + + parameter.setDeprecated( d.getChild( "deprecated" ).getValue() ); + + parameter.setImplementation( d.getChild( "implementation" ).getValue() ); + + parameters.add( parameter ); + } + + mojo.setParameters( parameters ); + + // TODO: this should not need to be handed off... + + // ---------------------------------------------------------------------- + // Configuration + // ---------------------------------------------------------------------- + + mojo.setMojoConfiguration( c.getChild( "configuration" ) ); + + // TODO: Go back to this when we get the container ready to configure mojos... + // mojo.setConfiguration( c.getChild( "configuration" ) ); + + // ---------------------------------------------------------------------- + // Requirements + // ---------------------------------------------------------------------- + + PlexusConfiguration[] requirements = c.getChild( "requirements" ).getChildren( "requirement" ); + + for ( int i = 0; i < requirements.length; i++ ) + { + PlexusConfiguration requirement = requirements[i]; + + ComponentRequirement cr = new ComponentRequirement(); + + cr.setRole( requirement.getChild( "role" ).getValue() ); + + cr.setRoleHint( requirement.getChild( "role-hint" ).getValue() ); + + cr.setFieldName( requirement.getChild( "field-name" ).getValue() ); + + mojo.addRequirement( cr ); + } + + return mojo; + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + public PlexusConfiguration buildConfiguration( Reader configuration ) + throws PlexusConfigurationException + { + try + { + return new XmlPlexusConfiguration( Xpp3DomBuilder.build( configuration ) ); + } + catch ( IOException e ) + { + throw new PlexusConfigurationException( "Error creating configuration", e ); + } + catch ( XmlPullParserException e ) + { + throw new PlexusConfigurationException( "Error creating configuration", e ); + } + } +} diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/Requirement.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/Requirement.java new file mode 100644 index 0000000000..9306408c0a --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/Requirement.java @@ -0,0 +1,55 @@ +package org.apache.maven.plugin.descriptor; + +/* + * 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. + */ + +/** + * Describes a component requirement. + * + * @author Brett Porter + * @version $Id$ + */ +public class Requirement +{ + private final String role; + + private final String roleHint; + + public Requirement( String role ) + { + this.role = role; + this.roleHint = null; + } + + public Requirement( String role, String roleHint ) + { + this.role = role; + this.roleHint = roleHint; + } + + public String getRole() + { + return role; + } + + public String getRoleHint() + { + return roleHint; + } +} diff --git a/maven-plugin-api/src/main/mdo/lifecycle.mdo b/maven-plugin-api/src/main/mdo/lifecycle.mdo new file mode 100644 index 0000000000..c70b57aa25 --- /dev/null +++ b/maven-plugin-api/src/main/mdo/lifecycle.mdo @@ -0,0 +1,125 @@ + + + + lifecycle-mappings + LifecycleMappings + + + + package + org.apache.maven.plugin.lifecycle + + + + + LifecycleConfiguration + 1.0.0 + Root element of the lifecycle.xml file. + + + lifecycles + 1.0.0 + + Lifecycle + * + + + + + + Lifecycle + 1.0.0 + + + + id + true + 1.0.0 + String + The ID of this lifecycle, for identification in the mojo descriptor. + + + phases + 1.0.0 + The phase mappings for this lifecycle. + + Phase + * + + + + + + Phase + 1.0.0 + A phase mapping definition. + + + id + true + 1.0.0 + String + The ID of this phase, eg <code>generate-sources</code>. + + + executions + 1.0.0 + The goals to execute within the phase. + + Execution + * + + + + configuration + 1.0.0 + DOM + Configuration to pass to all goals run in this phase. + + + + + Execution + 1.0.0 + A set of goals to execute. + + + configuration + 1.0.0 + DOM + Configuration to pass to the goals. + + + goals + 1.0.0 + The goals to execute. + + String + * + + + + + + diff --git a/maven-plugin-api/src/test/java/org/apache/maven/plugin/lifecycle/LifecycleXpp3ReaderTest.java b/maven-plugin-api/src/test/java/org/apache/maven/plugin/lifecycle/LifecycleXpp3ReaderTest.java new file mode 100644 index 0000000000..5f393c78e7 --- /dev/null +++ b/maven-plugin-api/src/test/java/org/apache/maven/plugin/lifecycle/LifecycleXpp3ReaderTest.java @@ -0,0 +1,57 @@ +package org.apache.maven.plugin.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. + */ + +import junit.framework.TestCase; +import org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Reader; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Test the lifecycle reader. + * + * @author Brett Porter + * @version $Id$ + */ +public class LifecycleXpp3ReaderTest + extends TestCase +{ + public void testLifecycleReader() + throws IOException, XmlPullParserException + { + LifecycleMappingsXpp3Reader reader = new LifecycleMappingsXpp3Reader(); + LifecycleConfiguration config = reader.read( new InputStreamReader( getClass().getResourceAsStream( "/lifecycle.xml" ) ) ); + assertEquals( "check number of lifecycles", 1, config.getLifecycles().size() ); + Lifecycle l = (Lifecycle) config.getLifecycles().iterator().next(); + assertEquals( "check id", "clover", l.getId() ); + assertEquals( "check number of phases", 1, l.getPhases().size() ); + Phase p = (Phase) l.getPhases().iterator().next(); + assertEquals( "check id", "generate-sources", p.getId() ); + assertEquals( "check number of executions", 1, p.getExecutions().size() ); + Execution e = (Execution) p.getExecutions().iterator().next(); + assertEquals( "check configuration", "true", ((Xpp3Dom) e.getConfiguration()).getChild( "debug" ).getValue() ); + assertEquals( "check number of goals", 1, e.getGoals().size() ); + String g = (String) e.getGoals().iterator().next(); + assertEquals( "check goal", "clover:compiler", g ); + } +} diff --git a/maven-plugin-api/src/test/resources/lifecycle.xml b/maven-plugin-api/src/test/resources/lifecycle.xml new file mode 100644 index 0000000000..ebec589255 --- /dev/null +++ b/maven-plugin-api/src/test/resources/lifecycle.xml @@ -0,0 +1,39 @@ + + + + + clover + + + generate-sources + + + + true + + + clover:compiler + + + + + + +