001package 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 022import java.util.HashMap; 023import java.util.LinkedList; 024import java.util.List; 025import java.util.Map; 026 027import org.apache.maven.plugin.Mojo; 028import org.codehaus.plexus.component.repository.ComponentDescriptor; 029import org.codehaus.plexus.configuration.PlexusConfiguration; 030import 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 */ 042public 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<>(); 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}