001 package org.apache.maven.tools.plugin.annotations; 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 com.thoughtworks.qdox.JavaDocBuilder; 023 import com.thoughtworks.qdox.model.DocletTag; 024 import com.thoughtworks.qdox.model.JavaClass; 025 import com.thoughtworks.qdox.model.JavaField; 026 import org.apache.maven.artifact.Artifact; 027 import org.apache.maven.artifact.factory.ArtifactFactory; 028 import org.apache.maven.artifact.resolver.ArtifactNotFoundException; 029 import org.apache.maven.artifact.resolver.ArtifactResolutionException; 030 import org.apache.maven.artifact.resolver.ArtifactResolver; 031 import org.apache.maven.plugin.descriptor.DuplicateParameterException; 032 import org.apache.maven.plugin.descriptor.InvalidParameterException; 033 import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; 034 import org.apache.maven.plugin.descriptor.MojoDescriptor; 035 import org.apache.maven.plugin.descriptor.PluginDescriptor; 036 import org.apache.maven.plugin.descriptor.Requirement; 037 import org.apache.maven.project.MavenProject; 038 import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; 039 import org.apache.maven.tools.plugin.ExtendedMojoDescriptor; 040 import org.apache.maven.tools.plugin.PluginToolsRequest; 041 import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent; 042 import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent; 043 import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent; 044 import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent; 045 import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotatedClass; 046 import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner; 047 import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScannerRequest; 048 import org.apache.maven.tools.plugin.extractor.ExtractionException; 049 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor; 050 import org.apache.maven.tools.plugin.util.PluginUtils; 051 import org.codehaus.plexus.archiver.UnArchiver; 052 import org.codehaus.plexus.archiver.manager.ArchiverManager; 053 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; 054 import org.codehaus.plexus.component.annotations.Component; 055 import org.codehaus.plexus.logging.AbstractLogEnabled; 056 import org.codehaus.plexus.util.StringUtils; 057 058 import java.io.File; 059 import java.util.ArrayList; 060 import java.util.Arrays; 061 import java.util.Collection; 062 import java.util.Collections; 063 import java.util.HashMap; 064 import java.util.HashSet; 065 import java.util.List; 066 import java.util.Map; 067 import java.util.Set; 068 import java.util.TreeMap; 069 import java.util.TreeSet; 070 071 /** 072 * JavaMojoDescriptorExtractor, a MojoDescriptor extractor to read descriptors from java classes with annotations. 073 * 074 * @author Olivier Lamy 075 * @since 3.0 076 */ 077 @Component( role = MojoDescriptorExtractor.class, hint = "java-annotations" ) 078 public class JavaAnnotationsMojoDescriptorExtractor 079 extends AbstractLogEnabled 080 implements MojoDescriptorExtractor 081 { 082 083 @org.codehaus.plexus.component.annotations.Requirement 084 private MojoAnnotationsScanner mojoAnnotationsScanner; 085 086 @org.codehaus.plexus.component.annotations.Requirement 087 private ArtifactResolver artifactResolver; 088 089 @org.codehaus.plexus.component.annotations.Requirement 090 private ArtifactFactory artifactFactory; 091 092 @org.codehaus.plexus.component.annotations.Requirement 093 private ArchiverManager archiverManager; 094 095 public List<MojoDescriptor> execute( MavenProject project, PluginDescriptor pluginDescriptor ) 096 throws ExtractionException, InvalidPluginDescriptorException 097 { 098 return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) ); 099 } 100 101 public List<MojoDescriptor> execute( PluginToolsRequest request ) 102 throws ExtractionException, InvalidPluginDescriptorException 103 { 104 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = scanAnnotations( request ); 105 106 Map<String, JavaClass> javaClassesMap = scanJavadoc( request, mojoAnnotatedClasses.values() ); 107 108 populateDataFromJavadoc( mojoAnnotatedClasses, javaClassesMap ); 109 110 return toMojoDescriptors( mojoAnnotatedClasses, request.getPluginDescriptor() ); 111 } 112 113 private Map<String, MojoAnnotatedClass> scanAnnotations( PluginToolsRequest request ) 114 throws ExtractionException 115 { 116 MojoAnnotationsScannerRequest mojoAnnotationsScannerRequest = new MojoAnnotationsScannerRequest(); 117 118 File output = new File( request.getProject().getBuild().getOutputDirectory() ); 119 mojoAnnotationsScannerRequest.setClassesDirectories( Arrays.asList( output ) ); 120 121 mojoAnnotationsScannerRequest.setDependencies( request.getDependencies() ); 122 123 mojoAnnotationsScannerRequest.setProject( request.getProject() ); 124 125 return mojoAnnotationsScanner.scan( mojoAnnotationsScannerRequest ); 126 } 127 128 private Map<String, JavaClass> scanJavadoc( PluginToolsRequest request, 129 Collection<MojoAnnotatedClass> mojoAnnotatedClasses ) 130 throws ExtractionException 131 { 132 // found artifact from reactors to scan sources 133 // we currently only scan sources from reactors 134 List<MavenProject> mavenProjects = new ArrayList<MavenProject>(); 135 136 // if we need to scan sources from external artifacts 137 Set<Artifact> externalArtifacts = new HashSet<Artifact>(); 138 139 for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses ) 140 { 141 if ( StringUtils.equals( mojoAnnotatedClass.getArtifact().getArtifactId(), 142 request.getProject().getArtifact().getArtifactId() ) ) 143 { 144 continue; 145 } 146 147 if ( !isMojoAnnnotatedClassCandidate( mojoAnnotatedClass ) ) 148 { 149 // we don't scan sources for classes without mojo annotations 150 continue; 151 } 152 153 MavenProject mavenProject = 154 getFromProjectReferences( mojoAnnotatedClass.getArtifact(), request.getProject() ); 155 156 if ( mavenProject != null ) 157 { 158 mavenProjects.add( mavenProject ); 159 } 160 else 161 { 162 externalArtifacts.add( mojoAnnotatedClass.getArtifact() ); 163 } 164 } 165 166 Map<String, JavaClass> javaClassesMap = new HashMap<String, JavaClass>(); 167 168 // try to get artifact with sources classifier, extract somewhere then scan for @since, @deprecated 169 for ( Artifact artifact : externalArtifacts ) 170 { 171 // parameter for test-sources too ?? olamy I need that for it test only 172 if ( StringUtils.equalsIgnoreCase( "tests", artifact.getClassifier() ) ) 173 { 174 javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "test-sources" ) ); 175 } 176 else 177 { 178 javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "sources" ) ); 179 } 180 181 } 182 183 for ( MavenProject mavenProject : mavenProjects ) 184 { 185 javaClassesMap.putAll( discoverClasses( request.getEncoding(), mavenProject ) ); 186 } 187 188 javaClassesMap.putAll( discoverClasses( request ) ); 189 190 return javaClassesMap; 191 } 192 193 private boolean isMojoAnnnotatedClassCandidate( MojoAnnotatedClass mojoAnnotatedClass ) 194 { 195 if ( mojoAnnotatedClass == null ) 196 { 197 return false; 198 } 199 return ( !mojoAnnotatedClass.getComponents().isEmpty() || !mojoAnnotatedClass.getParameters().isEmpty() 200 || mojoAnnotatedClass.getExecute() != null || mojoAnnotatedClass.getMojo() != null ); 201 202 } 203 204 protected Map<String, JavaClass> discoverClassesFromSourcesJar( Artifact artifact, PluginToolsRequest request, 205 String classifier ) 206 throws ExtractionException 207 { 208 try 209 { 210 Artifact sourcesArtifact = 211 artifactFactory.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(), 212 artifact.getVersion(), artifact.getType(), classifier ); 213 214 artifactResolver.resolve( sourcesArtifact, request.getRemoteRepos(), request.getLocal() ); 215 216 if ( sourcesArtifact.getFile() == null || !sourcesArtifact.getFile().exists() ) 217 { 218 // could not get artifact sources 219 return Collections.emptyMap(); 220 } 221 222 // extract sources to target/maven-plugin-plugin-sources/${groupId}/${artifact}/sources 223 File extractDirectory = new File( request.getProject().getBuild().getDirectory(), 224 "maven-plugin-plugin-sources/" + sourcesArtifact.getGroupId() + "/" 225 + sourcesArtifact.getArtifactId() + "/" + sourcesArtifact.getVersion() 226 + "/" + sourcesArtifact.getClassifier() ); 227 extractDirectory.mkdirs(); 228 229 UnArchiver unArchiver = archiverManager.getUnArchiver( "jar" ); 230 unArchiver.setSourceFile( sourcesArtifact.getFile() ); 231 unArchiver.setDestDirectory( extractDirectory ); 232 unArchiver.extract(); 233 234 return discoverClasses( request.getEncoding(), Arrays.asList( extractDirectory ) ); 235 } 236 catch ( ArtifactResolutionException e ) 237 { 238 throw new ExtractionException( e.getMessage(), e ); 239 } 240 catch ( ArtifactNotFoundException e ) 241 { 242 //throw new ExtractionException( e.getMessage(), e ); 243 getLogger().debug( "skip ArtifactNotFoundException:" + e.getMessage() ); 244 getLogger().warn( 245 "Unable to get sources artifact for " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" 246 + artifact.getVersion() + ". Some javadoc tags (@since, @deprecated and comments) won't be used" ); 247 return Collections.emptyMap(); 248 } 249 catch ( NoSuchArchiverException e ) 250 { 251 throw new ExtractionException( e.getMessage(), e ); 252 } 253 } 254 255 /** 256 * from sources scan to get @since and @deprecated and description of classes and fields. 257 * 258 * @param mojoAnnotatedClasses 259 * @param javaClassesMap 260 */ 261 protected void populateDataFromJavadoc( Map<String, MojoAnnotatedClass> mojoAnnotatedClasses, 262 Map<String, JavaClass> javaClassesMap ) 263 { 264 265 for ( Map.Entry<String, MojoAnnotatedClass> entry : mojoAnnotatedClasses.entrySet() ) 266 { 267 JavaClass javaClass = javaClassesMap.get( entry.getKey() ); 268 if ( javaClass == null ) 269 { 270 continue; 271 } 272 273 // populate class-level content 274 MojoAnnotationContent mojoAnnotationContent = entry.getValue().getMojo(); 275 if ( mojoAnnotationContent != null ) 276 { 277 mojoAnnotationContent.setDescription( javaClass.getComment() ); 278 279 DocletTag since = findInClassHierarchy( javaClass, "since" ); 280 if ( since != null ) 281 { 282 mojoAnnotationContent.setSince( since.getValue() ); 283 } 284 285 DocletTag deprecated = findInClassHierarchy( javaClass, "deprecated" ); 286 if ( deprecated != null ) 287 { 288 mojoAnnotationContent.setDeprecated( deprecated.getValue() ); 289 } 290 } 291 292 Map<String, JavaField> fieldsMap = extractFieldParameterTags( javaClass, javaClassesMap ); 293 294 // populate parameters 295 Map<String, ParameterAnnotationContent> parameters = 296 getParametersParentHierarchy( entry.getValue(), new HashMap<String, ParameterAnnotationContent>(), 297 mojoAnnotatedClasses ); 298 for ( Map.Entry<String, ParameterAnnotationContent> parameter : new TreeMap<String, ParameterAnnotationContent>( 299 parameters ).entrySet() ) 300 { 301 JavaField javaField = fieldsMap.get( parameter.getKey() ); 302 if ( javaField == null ) 303 { 304 continue; 305 } 306 307 ParameterAnnotationContent parameterAnnotationContent = parameter.getValue(); 308 parameterAnnotationContent.setDescription( javaField.getComment() ); 309 310 DocletTag deprecated = javaField.getTagByName( "deprecated" ); 311 if ( deprecated != null ) 312 { 313 parameterAnnotationContent.setDeprecated( deprecated.getValue() ); 314 } 315 316 DocletTag since = javaField.getTagByName( "since" ); 317 if ( since != null ) 318 { 319 parameterAnnotationContent.setSince( since.getValue() ); 320 } 321 } 322 323 // populate components 324 for ( Map.Entry<String, ComponentAnnotationContent> component : entry.getValue().getComponents().entrySet() ) 325 { 326 JavaField javaField = fieldsMap.get( component.getKey() ); 327 if ( javaField == null ) 328 { 329 continue; 330 } 331 332 ComponentAnnotationContent componentAnnotationContent = component.getValue(); 333 componentAnnotationContent.setDescription( javaField.getComment() ); 334 335 DocletTag deprecated = javaField.getTagByName( "deprecated" ); 336 if ( deprecated != null ) 337 { 338 componentAnnotationContent.setDeprecated( deprecated.getValue() ); 339 } 340 341 DocletTag since = javaField.getTagByName( "since" ); 342 if ( since != null ) 343 { 344 componentAnnotationContent.setSince( since.getValue() ); 345 } 346 } 347 348 } 349 350 } 351 352 /** 353 * @param javaClass not null 354 * @param tagName not null 355 * @return docletTag instance 356 */ 357 private DocletTag findInClassHierarchy( JavaClass javaClass, String tagName ) 358 { 359 DocletTag tag = javaClass.getTagByName( tagName ); 360 361 if ( tag == null ) 362 { 363 JavaClass superClass = javaClass.getSuperJavaClass(); 364 365 if ( superClass != null ) 366 { 367 tag = findInClassHierarchy( superClass, tagName ); 368 } 369 } 370 371 return tag; 372 } 373 374 /** 375 * extract fields that are either parameters or components. 376 * 377 * @param javaClass not null 378 * @return map with Mojo parameters names as keys 379 */ 380 private Map<String, JavaField> extractFieldParameterTags( JavaClass javaClass, 381 Map<String, JavaClass> javaClassesMap ) 382 { 383 Map<String, JavaField> rawParams = new TreeMap<String, com.thoughtworks.qdox.model.JavaField>(); 384 385 // we have to add the parent fields first, so that they will be overwritten by the local fields if 386 // that actually happens... 387 JavaClass superClass = javaClass.getSuperJavaClass(); 388 389 if ( superClass != null ) 390 { 391 if ( superClass.getFields().length > 0 ) 392 { 393 rawParams = extractFieldParameterTags( superClass, javaClassesMap ); 394 } 395 // maybe sources comes from scan of sources artifact 396 superClass = javaClassesMap.get( superClass.getFullyQualifiedName() ); 397 if ( superClass != null ) 398 { 399 rawParams = extractFieldParameterTags( superClass, javaClassesMap ); 400 } 401 } 402 else 403 { 404 405 rawParams = new TreeMap<String, JavaField>(); 406 } 407 408 JavaField[] classFields = javaClass.getFields(); 409 410 if ( classFields != null ) 411 { 412 for ( JavaField field : classFields ) 413 { 414 rawParams.put( field.getName(), field ); 415 } 416 } 417 return rawParams; 418 } 419 420 protected Map<String, JavaClass> discoverClasses( final PluginToolsRequest request ) 421 { 422 return discoverClasses( request.getEncoding(), request.getProject() ); 423 } 424 425 @SuppressWarnings( "unchecked" ) 426 protected Map<String, JavaClass> discoverClasses( final String encoding, final MavenProject project ) 427 { 428 List<File> sources = new ArrayList<File>(); 429 430 for ( String source : (List<String>) project.getCompileSourceRoots() ) 431 { 432 sources.add( new File( source ) ); 433 } 434 435 // TODO be more dynamic 436 File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" ); 437 if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() ) 438 && generatedPlugin.exists() ) 439 { 440 sources.add( generatedPlugin ); 441 } 442 443 return discoverClasses( encoding, sources ); 444 } 445 446 protected Map<String, JavaClass> discoverClasses( final String encoding, List<File> sourceDirectories ) 447 { 448 JavaDocBuilder builder = new JavaDocBuilder(); 449 builder.setEncoding( encoding ); 450 451 for ( File source : sourceDirectories ) 452 { 453 builder.addSourceTree( source ); 454 } 455 456 JavaClass[] javaClasses = builder.getClasses(); 457 458 if ( javaClasses == null || javaClasses.length < 1 ) 459 { 460 return Collections.emptyMap(); 461 } 462 463 Map<String, JavaClass> javaClassMap = new HashMap<String, JavaClass>( javaClasses.length ); 464 465 for ( JavaClass javaClass : javaClasses ) 466 { 467 javaClassMap.put( javaClass.getFullyQualifiedName(), javaClass ); 468 } 469 470 return javaClassMap; 471 } 472 473 private List<MojoDescriptor> toMojoDescriptors( Map<String, MojoAnnotatedClass> mojoAnnotatedClasses, 474 PluginDescriptor pluginDescriptor ) 475 throws DuplicateParameterException, InvalidParameterException 476 { 477 List<MojoDescriptor> mojoDescriptors = new ArrayList<MojoDescriptor>( mojoAnnotatedClasses.size() ); 478 for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses.values() ) 479 { 480 // no mojo so skip it 481 if ( mojoAnnotatedClass.getMojo() == null ) 482 { 483 continue; 484 } 485 486 ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor(); 487 488 //mojoDescriptor.setRole( mojoAnnotatedClass.getClassName() ); 489 //mojoDescriptor.setRoleHint( "default" ); 490 mojoDescriptor.setImplementation( mojoAnnotatedClass.getClassName() ); 491 mojoDescriptor.setLanguage( "java" ); 492 493 MojoAnnotationContent mojo = mojoAnnotatedClass.getMojo(); 494 495 mojoDescriptor.setDescription( mojo.getDescription() ); 496 mojoDescriptor.setSince( mojo.getSince() ); 497 mojo.setDeprecated( mojo.getDeprecated() ); 498 499 mojoDescriptor.setProjectRequired( mojo.requiresProject() ); 500 501 mojoDescriptor.setRequiresReports( mojo.requiresReports() ); 502 503 mojoDescriptor.setComponentConfigurator( mojo.configurator() ); 504 505 mojoDescriptor.setInheritedByDefault( mojo.inheritByDefault() ); 506 507 mojoDescriptor.setInstantiationStrategy( mojo.instantiationStrategy().id() ); 508 509 mojoDescriptor.setAggregator( mojo.aggregator() ); 510 mojoDescriptor.setDependencyResolutionRequired( mojo.requiresDependencyResolution().id() ); 511 mojoDescriptor.setDependencyCollectionRequired( mojo.requiresDependencyCollection().id() ); 512 513 mojoDescriptor.setDirectInvocationOnly( mojo.requiresDirectInvocation() ); 514 mojoDescriptor.setDeprecated( mojo.getDeprecated() ); 515 mojoDescriptor.setThreadSafe( mojo.threadSafe() ); 516 517 ExecuteAnnotationContent execute = findExecuteInParentHierarchy( mojoAnnotatedClass, mojoAnnotatedClasses ); 518 if ( execute != null ) 519 { 520 mojoDescriptor.setExecuteGoal( execute.goal() ); 521 mojoDescriptor.setExecuteLifecycle( execute.lifecycle() ); 522 if ( execute.phase() != null ) 523 { 524 mojoDescriptor.setExecutePhase( execute.phase().id() ); 525 } 526 } 527 528 mojoDescriptor.setExecutionStrategy( mojo.executionStrategy() ); 529 // ??? 530 //mojoDescriptor.alwaysExecute(mojo.a) 531 532 mojoDescriptor.setGoal( mojo.name() ); 533 mojoDescriptor.setOnlineRequired( mojo.requiresOnline() ); 534 535 mojoDescriptor.setPhase( mojo.defaultPhase().id() ); 536 537 // Parameter annotations 538 Map<String, ParameterAnnotationContent> parameters = 539 getParametersParentHierarchy( mojoAnnotatedClass, new HashMap<String, ParameterAnnotationContent>(), 540 mojoAnnotatedClasses ); 541 542 for ( ParameterAnnotationContent parameterAnnotationContent : new TreeSet<ParameterAnnotationContent>( 543 parameters.values() ) ) 544 { 545 org.apache.maven.plugin.descriptor.Parameter parameter = 546 new org.apache.maven.plugin.descriptor.Parameter(); 547 parameter.setName( parameterAnnotationContent.getFieldName() ); 548 parameter.setAlias( parameterAnnotationContent.alias() ); 549 parameter.setDefaultValue( parameterAnnotationContent.defaultValue() ); 550 parameter.setDeprecated( parameterAnnotationContent.getDeprecated() ); 551 parameter.setDescription( parameterAnnotationContent.getDescription() ); 552 parameter.setEditable( !parameterAnnotationContent.readonly() ); 553 String property = parameterAnnotationContent.property(); 554 if ( StringUtils.contains( property, '$' ) || StringUtils.contains( property, '{' ) 555 || StringUtils.contains( property, '}' ) ) 556 { 557 throw new InvalidParameterException( 558 "Invalid property for parameter '" + parameter.getName() + "', " + "forbidden characters ${}: " 559 + property, null ); 560 } 561 parameter.setExpression( StringUtils.isEmpty( property ) ? "" : "${" + property + "}" ); 562 parameter.setType( parameterAnnotationContent.getClassName() ); 563 parameter.setSince( parameterAnnotationContent.getSince() ); 564 parameter.setRequired( parameterAnnotationContent.required() ); 565 566 mojoDescriptor.addParameter( parameter ); 567 } 568 569 // Component annotations 570 Map<String, ComponentAnnotationContent> components = 571 getComponentsParentHierarchy( mojoAnnotatedClass, new HashMap<String, ComponentAnnotationContent>(), 572 mojoAnnotatedClasses ); 573 574 for ( ComponentAnnotationContent componentAnnotationContent : new TreeSet<ComponentAnnotationContent>( 575 components.values() ) ) 576 { 577 org.apache.maven.plugin.descriptor.Parameter parameter = 578 new org.apache.maven.plugin.descriptor.Parameter(); 579 parameter.setName( componentAnnotationContent.getFieldName() ); 580 581 // recognize Maven-injected objects as components annotations instead of parameters 582 String expression = PluginUtils.MAVEN_COMPONENTS.get( componentAnnotationContent.getRoleClassName() ); 583 if ( expression == null ) 584 { 585 // normal component 586 parameter.setRequirement( new Requirement( componentAnnotationContent.getRoleClassName(), 587 componentAnnotationContent.hint() ) ); 588 } 589 else 590 { 591 // not a component but a Maven object to be transformed into an expression/property 592 parameter.setDefaultValue( expression ); 593 parameter.setType( componentAnnotationContent.getRoleClassName() ); 594 parameter.setRequired( true ); 595 } 596 parameter.setDeprecated( componentAnnotationContent.getDeprecated() ); 597 parameter.setSince( componentAnnotationContent.getSince() ); 598 599 // same behaviour as JavaMojoDescriptorExtractor 600 //parameter.setRequired( ... ); 601 parameter.setEditable( false ); 602 603 mojoDescriptor.addParameter( parameter ); 604 } 605 606 mojoDescriptor.setPluginDescriptor( pluginDescriptor ); 607 608 mojoDescriptors.add( mojoDescriptor ); 609 } 610 return mojoDescriptors; 611 } 612 613 protected ExecuteAnnotationContent findExecuteInParentHierarchy( MojoAnnotatedClass mojoAnnotatedClass, 614 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 615 { 616 617 if ( mojoAnnotatedClass.getExecute() != null ) 618 { 619 return mojoAnnotatedClass.getExecute(); 620 } 621 String parentClassName = mojoAnnotatedClass.getParentClassName(); 622 if ( StringUtils.isEmpty( parentClassName ) ) 623 { 624 return null; 625 } 626 MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); 627 if ( parent == null ) 628 { 629 return null; 630 } 631 return findExecuteInParentHierarchy( parent, mojoAnnotatedClasses ); 632 } 633 634 635 protected Map<String, ParameterAnnotationContent> getParametersParentHierarchy( 636 MojoAnnotatedClass mojoAnnotatedClass, Map<String, ParameterAnnotationContent> parameters, 637 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 638 { 639 List<ParameterAnnotationContent> parameterAnnotationContents = new ArrayList<ParameterAnnotationContent>(); 640 641 parameterAnnotationContents = 642 getParametersParent( mojoAnnotatedClass, parameterAnnotationContents, mojoAnnotatedClasses ); 643 644 // move to parent first to build the Map 645 Collections.reverse( parameterAnnotationContents ); 646 647 Map<String, ParameterAnnotationContent> map = 648 new HashMap<String, ParameterAnnotationContent>( parameterAnnotationContents.size() ); 649 650 for ( ParameterAnnotationContent parameterAnnotationContent : parameterAnnotationContents ) 651 { 652 map.put( parameterAnnotationContent.getFieldName(), parameterAnnotationContent ); 653 } 654 return map; 655 } 656 657 protected List<ParameterAnnotationContent> getParametersParent( MojoAnnotatedClass mojoAnnotatedClass, 658 List<ParameterAnnotationContent> parameterAnnotationContents, 659 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 660 { 661 parameterAnnotationContents.addAll( mojoAnnotatedClass.getParameters().values() ); 662 String parentClassName = mojoAnnotatedClass.getParentClassName(); 663 if ( parentClassName != null ) 664 { 665 MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); 666 if ( parent != null ) 667 { 668 return getParametersParent( parent, parameterAnnotationContents, mojoAnnotatedClasses ); 669 } 670 } 671 return parameterAnnotationContents; 672 } 673 674 protected Map<String, ComponentAnnotationContent> getComponentsParentHierarchy( 675 MojoAnnotatedClass mojoAnnotatedClass, Map<String, ComponentAnnotationContent> components, 676 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 677 { 678 List<ComponentAnnotationContent> componentAnnotationContents = new ArrayList<ComponentAnnotationContent>(); 679 680 componentAnnotationContents = 681 getComponentParent( mojoAnnotatedClass, componentAnnotationContents, mojoAnnotatedClasses ); 682 683 // move to parent first to build the Map 684 Collections.reverse( componentAnnotationContents ); 685 686 Map<String, ComponentAnnotationContent> map = 687 new HashMap<String, ComponentAnnotationContent>( componentAnnotationContents.size() ); 688 689 for ( ComponentAnnotationContent componentAnnotationContent : componentAnnotationContents ) 690 { 691 map.put( componentAnnotationContent.getFieldName(), componentAnnotationContent ); 692 } 693 return map; 694 } 695 696 protected List<ComponentAnnotationContent> getComponentParent( MojoAnnotatedClass mojoAnnotatedClass, 697 List<ComponentAnnotationContent> componentAnnotationContents, 698 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 699 { 700 componentAnnotationContents.addAll( mojoAnnotatedClass.getComponents().values() ); 701 String parentClassName = mojoAnnotatedClass.getParentClassName(); 702 if ( parentClassName != null ) 703 { 704 MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); 705 if ( parent != null ) 706 { 707 return getComponentParent( parent, componentAnnotationContents, mojoAnnotatedClasses ); 708 } 709 } 710 return componentAnnotationContents; 711 } 712 713 protected MavenProject getFromProjectReferences( Artifact artifact, MavenProject project ) 714 { 715 if ( project.getProjectReferences() == null || project.getProjectReferences().isEmpty() ) 716 { 717 return null; 718 } 719 @SuppressWarnings( "unchecked" ) Collection<MavenProject> mavenProjects = 720 project.getProjectReferences().values(); 721 for ( MavenProject mavenProject : mavenProjects ) 722 { 723 if ( StringUtils.equals( mavenProject.getId(), artifact.getId() ) ) 724 { 725 return mavenProject; 726 } 727 } 728 return null; 729 } 730 731 }