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