View Javadoc

1   package org.apache.maven.plugin.descriptor;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.HashMap;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.apache.maven.plugin.Mojo;
28  import org.codehaus.plexus.component.repository.ComponentDescriptor;
29  import org.codehaus.plexus.configuration.PlexusConfiguration;
30  import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
31  
32  /**
33   * The bean containing the Mojo descriptor.
34   * <br/>
35   * For more information about the usage tag, have a look to:
36   * <a href="http://maven.apache.org/developers/mojo-api-specification.html">
37   * http://maven.apache.org/developers/mojo-api-specification.html</a>
38   *
39   * @todo is there a need for the delegation of MavenMojoDescriptor to this?
40   * Why not just extend ComponentDescriptor here?
41   */
42  public class MojoDescriptor
43      extends ComponentDescriptor<Mojo>
44      implements Cloneable
45  {
46      /** The Plexus component type */
47      public static final String MAVEN_PLUGIN = "maven-plugin";
48  
49      /** "once-per-session" execution strategy */
50      public static final String SINGLE_PASS_EXEC_STRATEGY = "once-per-session";
51  
52      /** "always" execution strategy */
53      public static final String MULTI_PASS_EXEC_STRATEGY = "always";
54  
55      private static final String DEFAULT_INSTANTIATION_STRATEGY = "per-lookup";
56  
57      private static final String DEFAULT_LANGUAGE = "java";
58  
59      private List<Parameter> parameters;
60  
61      private Map<String, Parameter> parameterMap;
62  
63      /** By default, the execution strategy is "once-per-session" */
64      private String executionStrategy = SINGLE_PASS_EXEC_STRATEGY;
65  
66      /**
67       * The goal name for the Mojo, that users will reference from the command line to execute the Mojo directly, or
68       * inside a POM in order to provide Mojo-specific configuration.
69       */
70      private String goal;
71  
72      /**
73       * Defines a default phase to bind a mojo execution to if the user does not explicitly set a phase in the POM.
74       * <i>Note:</i> This will not automagically make a mojo run when the plugin declaration is added to the POM. It
75       * merely enables the user to omit the <code>&lt;phase&gt;</code> element from the surrounding
76       * <code>&lt;execution&gt;</code> element.
77       */
78      private String phase;
79  
80      /** Specify the version when the Mojo was added to the API. Similar to Javadoc since. */
81      private String since;
82  
83      /** Reference the invocation phase of the Mojo. */
84      private String executePhase;
85  
86      /** Reference the invocation goal of the Mojo. */
87      private String executeGoal;
88  
89      /** Reference the invocation lifecycle of the Mojo. */
90      private String executeLifecycle;
91  
92      /**
93       * Specify the version when the Mojo was deprecated to the API. Similar to Javadoc deprecated. This will trigger a
94       * warning when a user tries to configure a parameter marked as deprecated.
95       */
96      private String deprecated;
97  
98      /**
99       * Flags this Mojo to run it in a multi module way, i.e. aggregate the build with the set of projects listed as
100      * modules. By default, no need to aggregate the Maven project and its child modules
101      */
102     private boolean aggregator = false;
103 
104     // ----------------------------------------------------------------------
105     //
106     // ----------------------------------------------------------------------
107 
108     /** Specify the required dependencies in a specified scope */
109     private String dependencyResolutionRequired = null;
110 
111     /** The scope of (transitive) dependencies that should be collected but not resolved. */
112     private String dependencyCollectionRequired;
113 
114     /**  By default, the Mojo needs a Maven project to be executed */
115     private boolean projectRequired = true;
116 
117     /**  By default, the Mojo is assumed to work offline as well */
118     private boolean onlineRequired = false;
119 
120     /**  Plugin configuration */
121     private PlexusConfiguration mojoConfiguration;
122 
123     /**  Plugin descriptor */
124     private PluginDescriptor pluginDescriptor;
125 
126     /**  By default, the Mojo is inherited */
127     private boolean inheritedByDefault = true;
128 
129     /**  By default, the Mojo cannot be invoked directly */
130     private boolean directInvocationOnly = false;
131 
132     /**  By default, the Mojo don't need reports to run */
133     private boolean requiresReports = false;
134 
135     /** By default, mojos are not threadsafe */
136     private boolean threadSafe = false;
137 
138     /**
139      * Default constructor.
140      */
141     public MojoDescriptor()
142     {
143         setInstantiationStrategy( DEFAULT_INSTANTIATION_STRATEGY );
144         setComponentFactory( DEFAULT_LANGUAGE );
145     }
146 
147     // ----------------------------------------------------------------------
148     //
149     // ----------------------------------------------------------------------
150 
151     /**
152      * @return the language of this Mojo, i.e. <code>java</code>
153      */
154     public String getLanguage()
155     {
156         return getComponentFactory();
157     }
158 
159     /**
160      * @param language the new language
161      */
162     public void setLanguage( String language )
163     {
164         setComponentFactory( language );
165     }
166 
167     /**
168      * @return <code>true</code> if the Mojo is deprecated, <code>false</code> otherwise.
169      */
170     public String getDeprecated()
171     {
172         return deprecated;
173     }
174 
175     /**
176      * @param deprecated <code>true</code> to deprecate the Mojo, <code>false</code> otherwise.
177      */
178     public void setDeprecated( String deprecated )
179     {
180         this.deprecated = deprecated;
181     }
182 
183     /**
184      * @return the list of parameters
185      */
186     public List<Parameter> getParameters()
187     {
188         return parameters;
189     }
190 
191     /**
192      * @param parameters the new list of parameters
193      * @throws DuplicateParameterException if any
194      */
195     public void setParameters( List<Parameter> parameters )
196         throws DuplicateParameterException
197     {
198         for ( Parameter parameter : parameters )
199         {
200             addParameter( parameter );
201         }
202     }
203 
204     /**
205      * @param parameter add a new parameter
206      * @throws DuplicateParameterException if any
207      */
208     public void addParameter( Parameter parameter )
209         throws DuplicateParameterException
210     {
211         if ( parameters != null && parameters.contains( parameter ) )
212         {
213             throw new DuplicateParameterException( parameter.getName()
214                 + " has been declared multiple times in mojo with goal: " + getGoal() + " (implementation: "
215                 + getImplementation() + ")" );
216         }
217 
218         if ( parameters == null )
219         {
220             parameters = new LinkedList<Parameter>();
221         }
222 
223         parameters.add( parameter );
224     }
225 
226     /**
227      * @return the list parameters as a Map
228      */
229     public Map<String, Parameter> getParameterMap()
230     {
231         if ( parameterMap == null )
232         {
233             parameterMap = new HashMap<String, Parameter>();
234 
235             if ( parameters != null )
236             {
237                 for ( Parameter pd : parameters )
238                 {
239                     parameterMap.put( pd.getName(), pd );
240                 }
241             }
242         }
243 
244         return parameterMap;
245     }
246 
247     // ----------------------------------------------------------------------
248     // Dependency requirement
249     // ----------------------------------------------------------------------
250 
251     /**
252      * @param requiresDependencyResolution the new required dependencies in a specified scope
253      */
254     public void setDependencyResolutionRequired( String requiresDependencyResolution )
255     {
256         this.dependencyResolutionRequired = requiresDependencyResolution;
257     }
258 
259     public String getDependencyResolutionRequired()
260     {
261         return dependencyResolutionRequired;
262     }
263 
264     /**
265      * @return the required dependencies in a specified scope
266      * @TODO the name is not intelligible
267      */
268     @Deprecated
269     public String isDependencyResolutionRequired()
270     {
271         return dependencyResolutionRequired;
272     }
273 
274     public void setDependencyCollectionRequired( String requiresDependencyCollection )
275     {
276         this.dependencyCollectionRequired = requiresDependencyCollection;
277     }
278 
279     /**
280      * Gets the scope of (transitive) dependencies that should be collected. Dependency collection refers to the process
281      * of calculating the complete dependency tree in terms of artifact coordinates. In contrast to dependency
282      * resolution, this does not include the download of the files for the dependency artifacts. It is meant for mojos
283      * that only want to analyze the set of transitive dependencies, in particular during early lifecycle phases where
284      * full dependency resolution might fail due to projects which haven't been built yet.
285      * 
286      * @return The scope of (transitive) dependencies that should be collected or {@code null} if none.
287      */
288     public String getDependencyCollectionRequired()
289     {
290         return dependencyCollectionRequired;
291     }
292 
293     // ----------------------------------------------------------------------
294     // Project requirement
295     // ----------------------------------------------------------------------
296 
297     /**
298      * @param requiresProject <code>true</code> if the Mojo needs a Maven project to be executed, <code>false</code>
299      * otherwise.
300      */
301     public void setProjectRequired( boolean requiresProject )
302     {
303         this.projectRequired = requiresProject;
304     }
305 
306     /**
307      * @return <code>true</code> if the Mojo needs a Maven project to be executed, <code>false</code> otherwise.
308      */
309     public boolean isProjectRequired()
310     {
311         return projectRequired;
312     }
313 
314     // ----------------------------------------------------------------------
315     // Online vs. Offline requirement
316     // ----------------------------------------------------------------------
317 
318     /**
319      * @param requiresOnline <code>true</code> if the Mojo is online, <code>false</code> otherwise.
320      */
321     public void setOnlineRequired( boolean requiresOnline )
322     {
323         this.onlineRequired = requiresOnline;
324     }
325 
326     /**
327      * @return <code>true</code> if the Mojo is online, <code>false</code> otherwise.
328      */
329     // blech! this isn't even intelligible as a method name. provided for
330     // consistency...
331     public boolean isOnlineRequired()
332     {
333         return onlineRequired;
334     }
335 
336     /**
337      * @return <code>true</code> if the Mojo is online, <code>false</code> otherwise.
338      */
339     // more english-friendly method...keep the code clean! :)
340     public boolean requiresOnline()
341     {
342         return onlineRequired;
343     }
344 
345     /**
346      * @return the binded phase name of the Mojo
347      */
348     public String getPhase()
349     {
350         return phase;
351     }
352 
353     /**
354      * @param phase the new binded phase name of the Mojo
355      */
356     public void setPhase( String phase )
357     {
358         this.phase = phase;
359     }
360 
361     /**
362      * @return the version when the Mojo was added to the API
363      */
364     public String getSince()
365     {
366         return since;
367     }
368 
369     /**
370      * @param since the new version when the Mojo was added to the API
371      */
372     public void setSince( String since )
373     {
374         this.since = since;
375     }
376 
377     /**
378      * @return The goal name of the Mojo
379      */
380     public String getGoal()
381     {
382         return goal;
383     }
384 
385     /**
386      * @param goal The new goal name of the Mojo
387      */
388     public void setGoal( String goal )
389     {
390         this.goal = goal;
391     }
392 
393     /**
394      * @return the invocation phase of the Mojo
395      */
396     public String getExecutePhase()
397     {
398         return executePhase;
399     }
400 
401     /**
402      * @param executePhase the new invocation phase of the Mojo
403      */
404     public void setExecutePhase( String executePhase )
405     {
406         this.executePhase = executePhase;
407     }
408 
409     /**
410      * @return <code>true</code> if the Mojo uses <code>always</code> for the <code>executionStrategy</code>
411      */
412     public boolean alwaysExecute()
413     {
414         return MULTI_PASS_EXEC_STRATEGY.equals( executionStrategy );
415     }
416 
417     /**
418      * @return the execution strategy
419      */
420     public String getExecutionStrategy()
421     {
422         return executionStrategy;
423     }
424 
425     /**
426      * @param executionStrategy the new execution strategy
427      */
428     public void setExecutionStrategy( String executionStrategy )
429     {
430         this.executionStrategy = executionStrategy;
431     }
432 
433     /**
434      * @return the mojo configuration
435      */
436     public PlexusConfiguration getMojoConfiguration()
437     {
438         if ( mojoConfiguration == null )
439         {
440             mojoConfiguration = new XmlPlexusConfiguration( "configuration" );
441         }
442         return mojoConfiguration;
443     }
444 
445     /**
446      * @param mojoConfiguration a new mojo configuration
447      */
448     public void setMojoConfiguration( PlexusConfiguration mojoConfiguration )
449     {
450         this.mojoConfiguration = mojoConfiguration;
451     }
452 
453     /** {@inheritDoc} */
454     public String getRole()
455     {
456         return Mojo.ROLE;
457     }
458 
459     /** {@inheritDoc} */
460     public String getRoleHint()
461     {
462         return getId();
463     }
464 
465     /**
466      * @return the id of the mojo, based on the goal name
467      */
468     public String getId()
469     {
470         return getPluginDescriptor().getId() + ":" + getGoal();
471     }
472 
473     /**
474      * @return the full goal name
475      * @see PluginDescriptor#getGoalPrefix()
476      * @see #getGoal()
477      */
478     public String getFullGoalName()
479     {
480         return getPluginDescriptor().getGoalPrefix() + ":" + getGoal();
481     }
482 
483     /** {@inheritDoc} */
484     public String getComponentType()
485     {
486         return MAVEN_PLUGIN;
487     }
488 
489     /**
490      * @return the plugin descriptor
491      */
492     public PluginDescriptor getPluginDescriptor()
493     {
494         return pluginDescriptor;
495     }
496 
497     /**
498      * @param pluginDescriptor the new plugin descriptor
499      */
500     public void setPluginDescriptor( PluginDescriptor pluginDescriptor )
501     {
502         this.pluginDescriptor = pluginDescriptor;
503     }
504 
505     /**
506      * @return <code>true</code> if the Mojo is herited, <code>false</code> otherwise.
507      */
508     public boolean isInheritedByDefault()
509     {
510         return inheritedByDefault;
511     }
512 
513     /**
514      * @param inheritedByDefault <code>true</code> if the Mojo is herited, <code>false</code> otherwise.
515      */
516     public void setInheritedByDefault( boolean inheritedByDefault )
517     {
518         this.inheritedByDefault = inheritedByDefault;
519     }
520 
521     /** {@inheritDoc} */
522     public boolean equals( Object object )
523     {
524         if ( this == object )
525         {
526             return true;
527         }
528 
529         if ( object instanceof MojoDescriptor )
530         {
531             MojoDescriptor other = (MojoDescriptor) object;
532 
533             if ( !compareObjects( getPluginDescriptor(), other.getPluginDescriptor() ) )
534             {
535                 return false;
536             }
537 
538             if ( !compareObjects( getGoal(), other.getGoal() ) )
539             {
540                 return false;
541             }
542 
543             return true;
544         }
545 
546         return false;
547     }
548 
549     private boolean compareObjects( Object first, Object second )
550     {
551         if ( ( first == null && second != null ) || ( first != null && second == null ) )
552         {
553             return false;
554         }
555 
556         return first.equals( second );
557     }
558 
559     /** {@inheritDoc} */
560     public int hashCode()
561     {
562         int result = 1;
563 
564         String goal = getGoal();
565 
566         if ( goal != null )
567         {
568             result += goal.hashCode();
569         }
570 
571         PluginDescriptor pd = getPluginDescriptor();
572 
573         if ( pd != null )
574         {
575             result -= pd.hashCode();
576         }
577 
578         return result;
579     }
580 
581     /**
582      * @return the invocation lifecycle of the Mojo
583      */
584     public String getExecuteLifecycle()
585     {
586         return executeLifecycle;
587     }
588 
589     /**
590      * @param executeLifecycle the new invocation lifecycle of the Mojo
591      */
592     public void setExecuteLifecycle( String executeLifecycle )
593     {
594         this.executeLifecycle = executeLifecycle;
595     }
596 
597     /**
598      * @param aggregator <code>true</code> if the Mojo uses the Maven project and its child modules,
599      * <code>false</code> otherwise.
600      */
601     public void setAggregator( boolean aggregator )
602     {
603         this.aggregator = aggregator;
604     }
605 
606     /**
607      * @return <code>true</code> if the Mojo uses the Maven project and its child modules,
608      * <code>false</code> otherwise.
609      */
610     public boolean isAggregator()
611     {
612         return aggregator;
613     }
614 
615     /**
616      * @return <code>true</code> if the Mojo cannot be invoked directly, <code>false</code> otherwise.
617      */
618     public boolean isDirectInvocationOnly()
619     {
620         return directInvocationOnly;
621     }
622 
623     /**
624      * @param directInvocationOnly <code>true</code> if the Mojo cannot be invoked directly,
625      * <code>false</code> otherwise.
626      */
627     public void setDirectInvocationOnly( boolean directInvocationOnly )
628     {
629         this.directInvocationOnly = directInvocationOnly;
630     }
631 
632     /**
633      * @return <code>true</code> if the Mojo needs reports to run, <code>false</code> otherwise.
634      */
635     public boolean isRequiresReports()
636     {
637         return requiresReports;
638     }
639 
640     /**
641      * @param requiresReports <code>true</code> if the Mojo needs reports to run, <code>false</code> otherwise.
642      */
643     public void setRequiresReports( boolean requiresReports )
644     {
645         this.requiresReports = requiresReports;
646     }
647 
648     /**
649      * @param executeGoal the new invocation goal of the Mojo
650      */
651     public void setExecuteGoal( String executeGoal )
652     {
653         this.executeGoal = executeGoal;
654     }
655 
656     /**
657      * @return the invocation goal of the Mojo
658      */
659     public String getExecuteGoal()
660     {
661         return executeGoal;
662     }
663 
664 
665     /**
666      * @return True if the <code>Mojo</code> is thread-safe and can be run safely in parallel
667      */
668     public boolean isThreadSafe()
669     {
670         return threadSafe;
671     }
672 
673     /**
674      * @param threadSafe indicates that the mojo is thread-safe and can be run safely in parallel
675      */
676     public void setThreadSafe( boolean threadSafe )
677     {
678         this.threadSafe = threadSafe;
679     }
680 
681     /**
682      * @return {@code true} if this mojo forks either a goal or the lifecycle, {@code false} otherwise.
683      */
684     public boolean isForking()
685     {
686         return ( getExecuteGoal() != null && getExecuteGoal().length() > 0 )
687             || ( getExecutePhase() != null && getExecutePhase().length() > 0 );
688     }
689 
690     /**
691      * Creates a shallow copy of this mojo descriptor.
692      */
693     @Override
694     public MojoDescriptor clone()
695     {
696         try
697         {
698             return (MojoDescriptor) super.clone();
699         }
700         catch ( CloneNotSupportedException e )
701         {
702             throw new UnsupportedOperationException( e );
703         }
704     }
705 
706 }