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 /** 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 }