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 }