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     /**
112      * The scope of (transitive) dependencies that should be collected but not resolved.
113      * @since 3.0-alpha-3
114      */
115     private String dependencyCollectionRequired;
116 
117     /**  By default, the Mojo needs a Maven project to be executed */
118     private boolean projectRequired = true;
119 
120     /**  By default, the Mojo is assumed to work offline as well */
121     private boolean onlineRequired = false;
122 
123     /**  Plugin configuration */
124     private PlexusConfiguration mojoConfiguration;
125 
126     /**  Plugin descriptor */
127     private PluginDescriptor pluginDescriptor;
128 
129     /**  By default, the Mojo is inherited */
130     private boolean inheritedByDefault = true;
131 
132     /**  By default, the Mojo cannot be invoked directly */
133     private boolean directInvocationOnly = false;
134 
135     /**  By default, the Mojo don't need reports to run */
136     private boolean requiresReports = false;
137 
138     /**
139      * By default, mojos are not threadsafe
140      * @since 3.0-beta-2
141      */
142     private boolean threadSafe = false;
143 
144     /**
145      * Default constructor.
146      */
147     public MojoDescriptor()
148     {
149         setInstantiationStrategy( DEFAULT_INSTANTIATION_STRATEGY );
150         setComponentFactory( DEFAULT_LANGUAGE );
151     }
152 
153     // ----------------------------------------------------------------------
154     //
155     // ----------------------------------------------------------------------
156 
157     /**
158      * @return the language of this Mojo, i.e. <code>java</code>
159      */
160     public String getLanguage()
161     {
162         return getComponentFactory();
163     }
164 
165     /**
166      * @param language the new language
167      */
168     public void setLanguage( String language )
169     {
170         setComponentFactory( language );
171     }
172 
173     /**
174      * @return <code>true</code> if the Mojo is deprecated, <code>false</code> otherwise.
175      */
176     public String getDeprecated()
177     {
178         return deprecated;
179     }
180 
181     /**
182      * @param deprecated <code>true</code> to deprecate the Mojo, <code>false</code> otherwise.
183      */
184     public void setDeprecated( String deprecated )
185     {
186         this.deprecated = deprecated;
187     }
188 
189     /**
190      * @return the list of parameters
191      */
192     public List<Parameter> getParameters()
193     {
194         return parameters;
195     }
196 
197     /**
198      * @param parameters the new list of parameters
199      * @throws DuplicateParameterException if any
200      */
201     public void setParameters( List<Parameter> parameters )
202         throws DuplicateParameterException
203     {
204         for ( Parameter parameter : parameters )
205         {
206             addParameter( parameter );
207         }
208     }
209 
210     /**
211      * @param parameter add a new parameter
212      * @throws DuplicateParameterException if any
213      */
214     public void addParameter( Parameter parameter )
215         throws DuplicateParameterException
216     {
217         if ( parameters != null && parameters.contains( parameter ) )
218         {
219             throw new DuplicateParameterException( parameter.getName()
220                 + " has been declared multiple times in mojo with goal: " + getGoal() + " (implementation: "
221                 + getImplementation() + ")" );
222         }
223 
224         if ( parameters == null )
225         {
226             parameters = new LinkedList<>();
227         }
228 
229         parameters.add( parameter );
230     }
231 
232     /**
233      * @return the list parameters as a Map
234      */
235     public Map<String, Parameter> getParameterMap()
236     {
237         if ( parameterMap == null )
238         {
239             parameterMap = new HashMap<>();
240 
241             if ( parameters != null )
242             {
243                 for ( Parameter pd : parameters )
244                 {
245                     parameterMap.put( pd.getName(), pd );
246                 }
247             }
248         }
249 
250         return parameterMap;
251     }
252 
253     // ----------------------------------------------------------------------
254     // Dependency requirement
255     // ----------------------------------------------------------------------
256 
257     /**
258      * @param requiresDependencyResolution the new required dependencies in a specified scope
259      */
260     public void setDependencyResolutionRequired( String requiresDependencyResolution )
261     {
262         this.dependencyResolutionRequired = requiresDependencyResolution;
263     }
264 
265     public String getDependencyResolutionRequired()
266     {
267         return dependencyResolutionRequired;
268     }
269 
270     /**
271      * @return the required dependencies in a specified scope
272      * @TODO the name is not intelligible
273      */
274     @Deprecated
275     public String isDependencyResolutionRequired()
276     {
277         return dependencyResolutionRequired;
278     }
279 
280     /**
281      * @since 3.0-alpha-3
282      */
283     public void setDependencyCollectionRequired( String requiresDependencyCollection )
284     {
285         this.dependencyCollectionRequired = requiresDependencyCollection;
286     }
287 
288     /**
289      * Gets the scope of (transitive) dependencies that should be collected. Dependency collection refers to the process
290      * of calculating the complete dependency tree in terms of artifact coordinates. In contrast to dependency
291      * resolution, this does not include the download of the files for the dependency artifacts. It is meant for mojos
292      * that only want to analyze the set of transitive dependencies, in particular during early lifecycle phases where
293      * full dependency resolution might fail due to projects which haven't been built yet.
294      *
295      * @return The scope of (transitive) dependencies that should be collected or {@code null} if none.
296      * @since 3.0-alpha-3
297      */
298     public String getDependencyCollectionRequired()
299     {
300         return dependencyCollectionRequired;
301     }
302 
303     // ----------------------------------------------------------------------
304     // Project requirement
305     // ----------------------------------------------------------------------
306 
307     /**
308      * @param requiresProject <code>true</code> if the Mojo needs a Maven project to be executed, <code>false</code>
309      * otherwise.
310      */
311     public void setProjectRequired( boolean requiresProject )
312     {
313         this.projectRequired = requiresProject;
314     }
315 
316     /**
317      * @return <code>true</code> if the Mojo needs a Maven project to be executed, <code>false</code> otherwise.
318      */
319     public boolean isProjectRequired()
320     {
321         return projectRequired;
322     }
323 
324     // ----------------------------------------------------------------------
325     // Online vs. Offline requirement
326     // ----------------------------------------------------------------------
327 
328     /**
329      * @param requiresOnline <code>true</code> if the Mojo is online, <code>false</code> otherwise.
330      */
331     public void setOnlineRequired( boolean requiresOnline )
332     {
333         this.onlineRequired = requiresOnline;
334     }
335 
336     /**
337      * @return <code>true</code> if the Mojo is online, <code>false</code> otherwise.
338      */
339     // blech! this isn't even intelligible as a method name. provided for
340     // consistency...
341     public boolean isOnlineRequired()
342     {
343         return onlineRequired;
344     }
345 
346     /**
347      * @return <code>true</code> if the Mojo is online, <code>false</code> otherwise.
348      */
349     // more english-friendly method...keep the code clean! :)
350     public boolean requiresOnline()
351     {
352         return onlineRequired;
353     }
354 
355     /**
356      * @return the binded phase name of the Mojo
357      */
358     public String getPhase()
359     {
360         return phase;
361     }
362 
363     /**
364      * @param phase the new binded phase name of the Mojo
365      */
366     public void setPhase( String phase )
367     {
368         this.phase = phase;
369     }
370 
371     /**
372      * @return the version when the Mojo was added to the API
373      */
374     public String getSince()
375     {
376         return since;
377     }
378 
379     /**
380      * @param since the new version when the Mojo was added to the API
381      */
382     public void setSince( String since )
383     {
384         this.since = since;
385     }
386 
387     /**
388      * @return The goal name of the Mojo
389      */
390     public String getGoal()
391     {
392         return goal;
393     }
394 
395     /**
396      * @param goal The new goal name of the Mojo
397      */
398     public void setGoal( String goal )
399     {
400         this.goal = goal;
401     }
402 
403     /**
404      * @return the invocation phase of the Mojo
405      */
406     public String getExecutePhase()
407     {
408         return executePhase;
409     }
410 
411     /**
412      * @param executePhase the new invocation phase of the Mojo
413      */
414     public void setExecutePhase( String executePhase )
415     {
416         this.executePhase = executePhase;
417     }
418 
419     /**
420      * @return <code>true</code> if the Mojo uses <code>always</code> for the <code>executionStrategy</code>
421      */
422     public boolean alwaysExecute()
423     {
424         return MULTI_PASS_EXEC_STRATEGY.equals( executionStrategy );
425     }
426 
427     /**
428      * @return the execution strategy
429      */
430     public String getExecutionStrategy()
431     {
432         return executionStrategy;
433     }
434 
435     /**
436      * @param executionStrategy the new execution strategy
437      */
438     public void setExecutionStrategy( String executionStrategy )
439     {
440         this.executionStrategy = executionStrategy;
441     }
442 
443     /**
444      * @return the mojo configuration
445      */
446     public PlexusConfiguration getMojoConfiguration()
447     {
448         if ( mojoConfiguration == null )
449         {
450             mojoConfiguration = new XmlPlexusConfiguration( "configuration" );
451         }
452         return mojoConfiguration;
453     }
454 
455     /**
456      * @param mojoConfiguration a new mojo configuration
457      */
458     public void setMojoConfiguration( PlexusConfiguration mojoConfiguration )
459     {
460         this.mojoConfiguration = mojoConfiguration;
461     }
462 
463     /** {@inheritDoc} */
464     public String getRole()
465     {
466         return Mojo.ROLE;
467     }
468 
469     /** {@inheritDoc} */
470     public String getRoleHint()
471     {
472         return getId();
473     }
474 
475     /**
476      * @return the id of the mojo, based on the goal name
477      */
478     public String getId()
479     {
480         return getPluginDescriptor().getId() + ":" + getGoal();
481     }
482 
483     /**
484      * @return the full goal name
485      * @see PluginDescriptor#getGoalPrefix()
486      * @see #getGoal()
487      */
488     public String getFullGoalName()
489     {
490         return getPluginDescriptor().getGoalPrefix() + ":" + getGoal();
491     }
492 
493     /** {@inheritDoc} */
494     public String getComponentType()
495     {
496         return MAVEN_PLUGIN;
497     }
498 
499     /**
500      * @return the plugin descriptor
501      */
502     public PluginDescriptor getPluginDescriptor()
503     {
504         return pluginDescriptor;
505     }
506 
507     /**
508      * @param pluginDescriptor the new plugin descriptor
509      */
510     public void setPluginDescriptor( PluginDescriptor pluginDescriptor )
511     {
512         this.pluginDescriptor = pluginDescriptor;
513     }
514 
515     /**
516      * @return <code>true</code> if the Mojo is herited, <code>false</code> otherwise.
517      */
518     public boolean isInheritedByDefault()
519     {
520         return inheritedByDefault;
521     }
522 
523     /**
524      * @param inheritedByDefault <code>true</code> if the Mojo is herited, <code>false</code> otherwise.
525      */
526     public void setInheritedByDefault( boolean inheritedByDefault )
527     {
528         this.inheritedByDefault = inheritedByDefault;
529     }
530 
531     /** {@inheritDoc} */
532     public boolean equals( Object object )
533     {
534         if ( this == object )
535         {
536             return true;
537         }
538 
539         if ( object instanceof MojoDescriptor )
540         {
541             MojoDescriptor other = (MojoDescriptor) object;
542 
543             if ( !compareObjects( getPluginDescriptor(), other.getPluginDescriptor() ) )
544             {
545                 return false;
546             }
547 
548             return compareObjects( getGoal(), other.getGoal() );
549 
550         }
551 
552         return false;
553     }
554 
555     private boolean compareObjects( Object first, Object second )
556     {
557         if ( first == second )
558         {
559             return true;
560         }
561 
562         if ( first == null || second == null )
563         {
564             return false;
565         }
566 
567         return first.equals( second );
568     }
569 
570     /** {@inheritDoc} */
571     public int hashCode()
572     {
573         int result = 1;
574 
575         String goal = getGoal();
576 
577         if ( goal != null )
578         {
579             result += goal.hashCode();
580         }
581 
582         PluginDescriptor pd = getPluginDescriptor();
583 
584         if ( pd != null )
585         {
586             result -= pd.hashCode();
587         }
588 
589         return result;
590     }
591 
592     /**
593      * @return the invocation lifecycle of the Mojo
594      */
595     public String getExecuteLifecycle()
596     {
597         return executeLifecycle;
598     }
599 
600     /**
601      * @param executeLifecycle the new invocation lifecycle of the Mojo
602      */
603     public void setExecuteLifecycle( String executeLifecycle )
604     {
605         this.executeLifecycle = executeLifecycle;
606     }
607 
608     /**
609      * @param aggregator <code>true</code> if the Mojo uses the Maven project and its child modules,
610      * <code>false</code> otherwise.
611      */
612     public void setAggregator( boolean aggregator )
613     {
614         this.aggregator = aggregator;
615     }
616 
617     /**
618      * @return <code>true</code> if the Mojo uses the Maven project and its child modules,
619      * <code>false</code> otherwise.
620      */
621     public boolean isAggregator()
622     {
623         return aggregator;
624     }
625 
626     /**
627      * @return <code>true</code> if the Mojo cannot be invoked directly, <code>false</code> otherwise.
628      */
629     public boolean isDirectInvocationOnly()
630     {
631         return directInvocationOnly;
632     }
633 
634     /**
635      * @param directInvocationOnly <code>true</code> if the Mojo cannot be invoked directly,
636      * <code>false</code> otherwise.
637      */
638     public void setDirectInvocationOnly( boolean directInvocationOnly )
639     {
640         this.directInvocationOnly = directInvocationOnly;
641     }
642 
643     /**
644      * @return <code>true</code> if the Mojo needs reports to run, <code>false</code> otherwise.
645      */
646     public boolean isRequiresReports()
647     {
648         return requiresReports;
649     }
650 
651     /**
652      * @param requiresReports <code>true</code> if the Mojo needs reports to run, <code>false</code> otherwise.
653      */
654     public void setRequiresReports( boolean requiresReports )
655     {
656         this.requiresReports = requiresReports;
657     }
658 
659     /**
660      * @param executeGoal the new invocation goal of the Mojo
661      */
662     public void setExecuteGoal( String executeGoal )
663     {
664         this.executeGoal = executeGoal;
665     }
666 
667     /**
668      * @return the invocation goal of the Mojo
669      */
670     public String getExecuteGoal()
671     {
672         return executeGoal;
673     }
674 
675 
676     /**
677      * @return True if the <code>Mojo</code> is thread-safe and can be run safely in parallel
678      * @since 3.0-beta-2
679      */
680     public boolean isThreadSafe()
681     {
682         return threadSafe;
683     }
684 
685     /**
686      * @param threadSafe indicates that the mojo is thread-safe and can be run safely in parallel
687      * @since 3.0-beta-2
688      */
689     public void setThreadSafe( boolean threadSafe )
690     {
691         this.threadSafe = threadSafe;
692     }
693 
694     /**
695      * @return {@code true} if this mojo forks either a goal or the lifecycle, {@code false} otherwise.
696      */
697     public boolean isForking()
698     {
699         return ( getExecuteGoal() != null && getExecuteGoal().length() > 0 )
700             || ( getExecutePhase() != null && getExecutePhase().length() > 0 );
701     }
702 
703     /**
704      * Creates a shallow copy of this mojo descriptor.
705      */
706     @Override
707     public MojoDescriptor clone()
708     {
709         try
710         {
711             return (MojoDescriptor) super.clone();
712         }
713         catch ( CloneNotSupportedException e )
714         {
715             throw new UnsupportedOperationException( e );
716         }
717     }
718 
719 }