001 package org.apache.maven.plugin.descriptor;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.util.HashMap;
023 import java.util.LinkedList;
024 import java.util.List;
025 import java.util.Map;
026
027 import org.apache.maven.plugin.Mojo;
028 import org.codehaus.plexus.component.repository.ComponentDescriptor;
029 import org.codehaus.plexus.configuration.PlexusConfiguration;
030 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
031
032 /**
033 * The bean containing the Mojo descriptor.
034 * <br/>
035 * For more information about the usage tag, have a look to:
036 * <a href="http://maven.apache.org/developers/mojo-api-specification.html">
037 * http://maven.apache.org/developers/mojo-api-specification.html</a>
038 *
039 * @todo is there a need for the delegation of MavenMojoDescriptor to this?
040 * Why not just extend ComponentDescriptor here?
041 */
042 public class MojoDescriptor
043 extends ComponentDescriptor<Mojo>
044 implements Cloneable
045 {
046 /** The Plexus component type */
047 public static final String MAVEN_PLUGIN = "maven-plugin";
048
049 /** "once-per-session" execution strategy */
050 public static final String SINGLE_PASS_EXEC_STRATEGY = "once-per-session";
051
052 /** "always" execution strategy */
053 public static final String MULTI_PASS_EXEC_STRATEGY = "always";
054
055 private static final String DEFAULT_INSTANTIATION_STRATEGY = "per-lookup";
056
057 private static final String DEFAULT_LANGUAGE = "java";
058
059 private List<Parameter> parameters;
060
061 private Map<String, Parameter> parameterMap;
062
063 /** By default, the execution strategy is "once-per-session" */
064 private String executionStrategy = SINGLE_PASS_EXEC_STRATEGY;
065
066 /**
067 * The goal name for the Mojo, that users will reference from the command line to execute the Mojo directly, or
068 * inside a POM in order to provide Mojo-specific configuration.
069 */
070 private String goal;
071
072 /**
073 * Defines a default phase to bind a mojo execution to if the user does not explicitly set a phase in the POM.
074 * <i>Note:</i> This will not automagically make a mojo run when the plugin declaration is added to the POM. It
075 * merely enables the user to omit the <code><phase></code> element from the surrounding
076 * <code><execution></code> element.
077 */
078 private String phase;
079
080 /** Specify the version when the Mojo was added to the API. Similar to Javadoc since. */
081 private String since;
082
083 /** Reference the invocation phase of the Mojo. */
084 private String executePhase;
085
086 /** Reference the invocation goal of the Mojo. */
087 private String executeGoal;
088
089 /** Reference the invocation lifecycle of the Mojo. */
090 private String executeLifecycle;
091
092 /**
093 * Specify the version when the Mojo was deprecated to the API. Similar to Javadoc deprecated. This will trigger a
094 * warning when a user tries to configure a parameter marked as deprecated.
095 */
096 private String deprecated;
097
098 /**
099 * 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<Parameter>();
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<String, Parameter>();
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 == null && second != null ) || ( first != null && second == null ) )
558 {
559 return false;
560 }
561
562 return first.equals( second );
563 }
564
565 /** {@inheritDoc} */
566 public int hashCode()
567 {
568 int result = 1;
569
570 String goal = getGoal();
571
572 if ( goal != null )
573 {
574 result += goal.hashCode();
575 }
576
577 PluginDescriptor pd = getPluginDescriptor();
578
579 if ( pd != null )
580 {
581 result -= pd.hashCode();
582 }
583
584 return result;
585 }
586
587 /**
588 * @return the invocation lifecycle of the Mojo
589 */
590 public String getExecuteLifecycle()
591 {
592 return executeLifecycle;
593 }
594
595 /**
596 * @param executeLifecycle the new invocation lifecycle of the Mojo
597 */
598 public void setExecuteLifecycle( String executeLifecycle )
599 {
600 this.executeLifecycle = executeLifecycle;
601 }
602
603 /**
604 * @param aggregator <code>true</code> if the Mojo uses the Maven project and its child modules,
605 * <code>false</code> otherwise.
606 */
607 public void setAggregator( boolean aggregator )
608 {
609 this.aggregator = aggregator;
610 }
611
612 /**
613 * @return <code>true</code> if the Mojo uses the Maven project and its child modules,
614 * <code>false</code> otherwise.
615 */
616 public boolean isAggregator()
617 {
618 return aggregator;
619 }
620
621 /**
622 * @return <code>true</code> if the Mojo cannot be invoked directly, <code>false</code> otherwise.
623 */
624 public boolean isDirectInvocationOnly()
625 {
626 return directInvocationOnly;
627 }
628
629 /**
630 * @param directInvocationOnly <code>true</code> if the Mojo cannot be invoked directly,
631 * <code>false</code> otherwise.
632 */
633 public void setDirectInvocationOnly( boolean directInvocationOnly )
634 {
635 this.directInvocationOnly = directInvocationOnly;
636 }
637
638 /**
639 * @return <code>true</code> if the Mojo needs reports to run, <code>false</code> otherwise.
640 */
641 public boolean isRequiresReports()
642 {
643 return requiresReports;
644 }
645
646 /**
647 * @param requiresReports <code>true</code> if the Mojo needs reports to run, <code>false</code> otherwise.
648 */
649 public void setRequiresReports( boolean requiresReports )
650 {
651 this.requiresReports = requiresReports;
652 }
653
654 /**
655 * @param executeGoal the new invocation goal of the Mojo
656 */
657 public void setExecuteGoal( String executeGoal )
658 {
659 this.executeGoal = executeGoal;
660 }
661
662 /**
663 * @return the invocation goal of the Mojo
664 */
665 public String getExecuteGoal()
666 {
667 return executeGoal;
668 }
669
670
671 /**
672 * @return True if the <code>Mojo</code> is thread-safe and can be run safely in parallel
673 * @since 3.0-beta-2
674 */
675 public boolean isThreadSafe()
676 {
677 return threadSafe;
678 }
679
680 /**
681 * @param threadSafe indicates that the mojo is thread-safe and can be run safely in parallel
682 * @since 3.0-beta-2
683 */
684 public void setThreadSafe( boolean threadSafe )
685 {
686 this.threadSafe = threadSafe;
687 }
688
689 /**
690 * @return {@code true} if this mojo forks either a goal or the lifecycle, {@code false} otherwise.
691 */
692 public boolean isForking()
693 {
694 return ( getExecuteGoal() != null && getExecuteGoal().length() > 0 )
695 || ( getExecutePhase() != null && getExecutePhase().length() > 0 );
696 }
697
698 /**
699 * Creates a shallow copy of this mojo descriptor.
700 */
701 @Override
702 public MojoDescriptor clone()
703 {
704 try
705 {
706 return (MojoDescriptor) super.clone();
707 }
708 catch ( CloneNotSupportedException e )
709 {
710 throw new UnsupportedOperationException( e );
711 }
712 }
713
714 }