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 java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; 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; /** * The bean containing the Mojo descriptor. * <br/> * For more information about the usage tag, have a look to: * <a href="http://maven.apache.org/developers/mojo-api-specification.html"> * http://maven.apache.org/developers/mojo-api-specification.html</a> * * @todo is there a need for the delegation of MavenMojoDescriptor to this? * Why not just extend ComponentDescriptor here? */ public class MojoDescriptor extends ComponentDescriptor<Mojo> implements Cloneable { /** The Plexus component type */ public static final String MAVEN_PLUGIN = "maven-plugin"; /** "once-per-session" execution strategy */ public static final String SINGLE_PASS_EXEC_STRATEGY = "once-per-session"; /** "always" execution strategy */ 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<Parameter> parameters; private Map<String, Parameter> parameterMap; /** By default, the execution strategy is "once-per-session" */ private String executionStrategy = SINGLE_PASS_EXEC_STRATEGY; /** * The goal name for the Mojo, that users will reference from the command line to execute the Mojo directly, or * inside a POM in order to provide Mojo-specific configuration. */ private String goal; /** * Defines a default phase to bind a mojo execution to if the user does not explicitly set a phase in the POM. * <i>Note:</i> This will not automagically make a mojo run when the plugin declaration is added to the POM. It * merely enables the user to omit the <code><phase></code> element from the surrounding * <code><execution></code> element. */ private String phase; /** Specify the version when the Mojo was added to the API. Similar to Javadoc since. */ private String since; /** Reference the invocation phase of the Mojo. */ private String executePhase; /** Reference the invocation goal of the Mojo. */ private String executeGoal; /** Reference the invocation lifecycle of the Mojo. */ private String executeLifecycle; /** * Specify the version when the Mojo was deprecated to the API. Similar to Javadoc deprecated. This will trigger a * warning when a user tries to configure a parameter marked as deprecated. */ private String deprecated; /** * Flags this Mojo to run it in a multi module way, i.e. aggregate the build with the set of projects listed as * modules. By default, no need to aggregate the Maven project and its child modules */ private boolean aggregator = false; // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- /** Specify the required dependencies in a specified scope */ private String dependencyResolutionRequired = null; /** The scope of (transitive) dependencies that should be collected but not resolved. */ private String dependencyCollectionRequired; /** By default, the Mojo needs a Maven project to be executed */ private boolean projectRequired = true; /** By default, the Mojo is assumed to work offline as well */ private boolean onlineRequired = false; /** Plugin configuration */ private PlexusConfiguration mojoConfiguration; /** Plugin descriptor */ private PluginDescriptor pluginDescriptor; /** By default, the Mojo is inherited */ private boolean inheritedByDefault = true; /** By default, the Mojo cannot be invoked directly */ private boolean directInvocationOnly = false; /** By default, the Mojo don't need reports to run */ private boolean requiresReports = false; /** By default, mojos are not threadsafe */ private boolean threadSafe = false; /** * Default constructor. */ public MojoDescriptor() { setInstantiationStrategy( DEFAULT_INSTANTIATION_STRATEGY ); setComponentFactory( DEFAULT_LANGUAGE ); } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- /** * @return the language of this Mojo, i.e. <code>java</code> */ public String getLanguage() { return getComponentFactory(); } /** * @param language the new language */ public void setLanguage( String language ) { setComponentFactory( language ); } /** * @return <code>true</code> if the Mojo is deprecated, <code>false</code> otherwise. */ public String getDeprecated() { return deprecated; } /** * @param deprecated <code>true</code> to deprecate the Mojo, <code>false</code> otherwise. */ public void setDeprecated( String deprecated ) { this.deprecated = deprecated; } /** * @return the list of parameters */ public List<Parameter> getParameters() { return parameters; } /** * @param parameters the new list of parameters * @throws DuplicateParameterException if any */ public void setParameters( List<Parameter> parameters ) throws DuplicateParameterException { for ( Parameter parameter : parameters ) { addParameter( parameter ); } } /** * @param parameter add a new parameter * @throws DuplicateParameterException if any */ 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() + ")" ); } if ( parameters == null ) { parameters = new LinkedList<Parameter>(); } parameters.add( parameter ); } /** * @return the list parameters as a Map */ public Map<String, Parameter> getParameterMap() { if ( parameterMap == null ) { parameterMap = new HashMap<String, Parameter>(); if ( parameters != null ) { for ( Parameter pd : parameters ) { parameterMap.put( pd.getName(), pd ); } } } return parameterMap; } // ---------------------------------------------------------------------- // Dependency requirement // ---------------------------------------------------------------------- /** * @param requiresDependencyResolution the new required dependencies in a specified scope */ public void setDependencyResolutionRequired( String requiresDependencyResolution ) { this.dependencyResolutionRequired = requiresDependencyResolution; } public String getDependencyResolutionRequired() { return dependencyResolutionRequired; } /** * @return the required dependencies in a specified scope * @TODO the name is not intelligible */ @Deprecated public String isDependencyResolutionRequired() { return dependencyResolutionRequired; } public void setDependencyCollectionRequired( String requiresDependencyCollection ) { this.dependencyCollectionRequired = requiresDependencyCollection; } /** * Gets the scope of (transitive) dependencies that should be collected. Dependency collection refers to the process * of calculating the complete dependency tree in terms of artifact coordinates. In contrast to dependency * resolution, this does not include the download of the files for the dependency artifacts. It is meant for mojos * that only want to analyze the set of transitive dependencies, in particular during early lifecycle phases where * full dependency resolution might fail due to projects which haven't been built yet. * * @return The scope of (transitive) dependencies that should be collected or {@code null} if none. */ public String getDependencyCollectionRequired() { return dependencyCollectionRequired; } // ---------------------------------------------------------------------- // Project requirement // ---------------------------------------------------------------------- /** * @param requiresProject <code>true</code> if the Mojo needs a Maven project to be executed, <code>false</code> * otherwise. */ public void setProjectRequired( boolean requiresProject ) { this.projectRequired = requiresProject; } /** * @return <code>true</code> if the Mojo needs a Maven project to be executed, <code>false</code> otherwise. */ public boolean isProjectRequired() { return projectRequired; } // ---------------------------------------------------------------------- // Online vs. Offline requirement // ---------------------------------------------------------------------- /** * @param requiresOnline <code>true</code> if the Mojo is online, <code>false</code> otherwise. */ public void setOnlineRequired( boolean requiresOnline ) { this.onlineRequired = requiresOnline; } /** * @return <code>true</code> if the Mojo is online, <code>false</code> otherwise. */ // blech! this isn't even intelligible as a method name. provided for // consistency... public boolean isOnlineRequired() { return onlineRequired; } /** * @return <code>true</code> if the Mojo is online, <code>false</code> otherwise. */ // more english-friendly method...keep the code clean! :) public boolean requiresOnline() { return onlineRequired; } /** * @return the binded phase name of the Mojo */ public String getPhase() { return phase; } /** * @param phase the new binded phase name of the Mojo */ public void setPhase( String phase ) { this.phase = phase; } /** * @return the version when the Mojo was added to the API */ public String getSince() { return since; } /** * @param since the new version when the Mojo was added to the API */ public void setSince( String since ) { this.since = since; } /** * @return The goal name of the Mojo */ public String getGoal() { return goal; } /** * @param goal The new goal name of the Mojo */ public void setGoal( String goal ) { this.goal = goal; } /** * @return the invocation phase of the Mojo */ public String getExecutePhase() { return executePhase; } /** * @param executePhase the new invocation phase of the Mojo */ public void setExecutePhase( String executePhase ) { this.executePhase = executePhase; } /** * @return <code>true</code> if the Mojo uses <code>always</code> for the <code>executionStrategy</code> */ public boolean alwaysExecute() { return MULTI_PASS_EXEC_STRATEGY.equals( executionStrategy ); } /** * @return the execution strategy */ public String getExecutionStrategy() { return executionStrategy; } /** * @param executionStrategy the new execution strategy */ public void setExecutionStrategy( String executionStrategy ) { this.executionStrategy = executionStrategy; } /** * @return the mojo configuration */ public PlexusConfiguration getMojoConfiguration() { if ( mojoConfiguration == null ) { mojoConfiguration = new XmlPlexusConfiguration( "configuration" ); } return mojoConfiguration; } /** * @param mojoConfiguration a new mojo configuration */ public void setMojoConfiguration( PlexusConfiguration mojoConfiguration ) { this.mojoConfiguration = mojoConfiguration; } /** {@inheritDoc} */ public String getRole() { return Mojo.ROLE; } /** {@inheritDoc} */ public String getRoleHint() { return getId(); } /** * @return the id of the mojo, based on the goal name */ public String getId() { return getPluginDescriptor().getId() + ":" + getGoal(); } /** * @return the full goal name * @see PluginDescriptor#getGoalPrefix() * @see #getGoal() */ public String getFullGoalName() { return getPluginDescriptor().getGoalPrefix() + ":" + getGoal(); } /** {@inheritDoc} */ public String getComponentType() { return MAVEN_PLUGIN; } /** * @return the plugin descriptor */ public PluginDescriptor getPluginDescriptor() { return pluginDescriptor; } /** * @param pluginDescriptor the new plugin descriptor */ public void setPluginDescriptor( PluginDescriptor pluginDescriptor ) { this.pluginDescriptor = pluginDescriptor; } /** * @return <code>true</code> if the Mojo is herited, <code>false</code> otherwise. */ public boolean isInheritedByDefault() { return inheritedByDefault; } /** * @param inheritedByDefault <code>true</code> if the Mojo is herited, <code>false</code> otherwise. */ public void setInheritedByDefault( boolean inheritedByDefault ) { this.inheritedByDefault = inheritedByDefault; } /** {@inheritDoc} */ 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; } return first.equals( second ); } /** {@inheritDoc} */ 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; } /** * @return the invocation lifecycle of the Mojo */ public String getExecuteLifecycle() { return executeLifecycle; } /** * @param executeLifecycle the new invocation lifecycle of the Mojo */ public void setExecuteLifecycle( String executeLifecycle ) { this.executeLifecycle = executeLifecycle; } /** * @param aggregator <code>true</code> if the Mojo uses the Maven project and its child modules, * <code>false</code> otherwise. */ public void setAggregator( boolean aggregator ) { this.aggregator = aggregator; } /** * @return <code>true</code> if the Mojo uses the Maven project and its child modules, * <code>false</code> otherwise. */ public boolean isAggregator() { return aggregator; } /** * @return <code>true</code> if the Mojo cannot be invoked directly, <code>false</code> otherwise. */ public boolean isDirectInvocationOnly() { return directInvocationOnly; } /** * @param directInvocationOnly <code>true</code> if the Mojo cannot be invoked directly, * <code>false</code> otherwise. */ public void setDirectInvocationOnly( boolean directInvocationOnly ) { this.directInvocationOnly = directInvocationOnly; } /** * @return <code>true</code> if the Mojo needs reports to run, <code>false</code> otherwise. */ public boolean isRequiresReports() { return requiresReports; } /** * @param requiresReports <code>true</code> if the Mojo needs reports to run, <code>false</code> otherwise. */ public void setRequiresReports( boolean requiresReports ) { this.requiresReports = requiresReports; } /** * @param executeGoal the new invocation goal of the Mojo */ public void setExecuteGoal( String executeGoal ) { this.executeGoal = executeGoal; } /** * @return the invocation goal of the Mojo */ public String getExecuteGoal() { return executeGoal; } /** * @return True if the <code>Mojo</code> is thread-safe and can be run safely in parallel */ public boolean isThreadSafe() { return threadSafe; } /** * @param threadSafe indicates that the mojo is thread-safe and can be run safely in parallel */ public void setThreadSafe( boolean threadSafe ) { this.threadSafe = threadSafe; } /** * @return {@code true} if this mojo forks either a goal or the lifecycle, {@code false} otherwise. */ public boolean isForking() { return ( getExecuteGoal() != null && getExecuteGoal().length() > 0 ) || ( getExecutePhase() != null && getExecutePhase().length() > 0 ); } /** * Creates a shallow copy of this mojo descriptor. */ @Override public MojoDescriptor clone() { try { return (MojoDescriptor) super.clone(); } catch ( CloneNotSupportedException e ) { throw new UnsupportedOperationException( e ); } } }