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 mojoDescriptor.setExecutePhase( execute.phase().id() ); 523 } 524 525 mojoDescriptor.setExecutionStrategy( mojo.executionStrategy() ); 526 // ??? 527 //mojoDescriptor.alwaysExecute(mojo.a) 528 529 mojoDescriptor.setGoal( mojo.name() ); 530 mojoDescriptor.setOnlineRequired( mojo.requiresOnline() ); 531 532 mojoDescriptor.setPhase( mojo.defaultPhase().id() ); 533 534 Map<String, ParameterAnnotationContent> parameters = 535 getParametersParentHierarchy( mojoAnnotatedClass, new HashMap<String, ParameterAnnotationContent>(), 536 mojoAnnotatedClasses ); 537 538 for ( ParameterAnnotationContent parameterAnnotationContent : new TreeSet<ParameterAnnotationContent>( 539 parameters.values() ) ) 540 { 541 org.apache.maven.plugin.descriptor.Parameter parameter = 542 new org.apache.maven.plugin.descriptor.Parameter(); 543 parameter.setName( parameterAnnotationContent.getFieldName() ); 544 parameter.setAlias( parameterAnnotationContent.alias() ); 545 parameter.setDefaultValue( parameterAnnotationContent.defaultValue() ); 546 parameter.setDeprecated( parameterAnnotationContent.getDeprecated() ); 547 parameter.setDescription( parameterAnnotationContent.getDescription() ); 548 parameter.setEditable( !parameterAnnotationContent.readonly() ); 549 String property = parameterAnnotationContent.property(); 550 if ( StringUtils.contains( property, '$' ) || StringUtils.contains( property, '{' ) 551 || StringUtils.contains( property, '}' ) ) 552 { 553 throw new InvalidParameterException( 554 "Invalid property for parameter '" + parameter.getName() + "', " + "forbidden characters ${}: " 555 + property, null ); 556 } 557 parameter.setExpression( StringUtils.isEmpty( property ) ? "" : "${" + property + "}" ); 558 parameter.setType( parameterAnnotationContent.getClassName() ); 559 parameter.setSince( parameterAnnotationContent.getSince() ); 560 parameter.setRequired( parameterAnnotationContent.required() ); 561 562 mojoDescriptor.addParameter( parameter ); 563 } 564 565 Map<String, ComponentAnnotationContent> components = 566 getComponentsParentHierarchy( mojoAnnotatedClass, new HashMap<String, ComponentAnnotationContent>(), 567 mojoAnnotatedClasses ); 568 569 for ( ComponentAnnotationContent componentAnnotationContent : new TreeSet<ComponentAnnotationContent>( 570 components.values() ) ) 571 { 572 org.apache.maven.plugin.descriptor.Parameter parameter = 573 new org.apache.maven.plugin.descriptor.Parameter(); 574 parameter.setName( componentAnnotationContent.getFieldName() ); 575 576 String expression = PluginUtils.MAVEN_COMPONENTS.get( componentAnnotationContent.getRoleClassName() ); 577 if ( expression == null ) 578 { 579 parameter.setRequirement( new Requirement( componentAnnotationContent.getRoleClassName(), 580 componentAnnotationContent.hint() ) ); 581 } 582 else 583 { 584 parameter.setDefaultValue( expression ); 585 parameter.setImplementation( componentAnnotationContent.getRoleClassName() ); 586 parameter.setType( componentAnnotationContent.getRoleClassName() ); 587 } 588 parameter.setDeprecated( componentAnnotationContent.getDeprecated() ); 589 parameter.setSince( componentAnnotationContent.getSince() ); 590 591 // same behaviour as JavaMojoDescriptorExtractor 592 //parameter.setRequired( ... ); 593 parameter.setEditable( false ); 594 mojoDescriptor.addParameter( parameter ); 595 } 596 597 mojoDescriptor.setPluginDescriptor( pluginDescriptor ); 598 599 mojoDescriptors.add( mojoDescriptor ); 600 } 601 return mojoDescriptors; 602 } 603 604 protected ExecuteAnnotationContent findExecuteInParentHierarchy( MojoAnnotatedClass mojoAnnotatedClass, 605 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 606 { 607 608 if ( mojoAnnotatedClass.getExecute() != null ) 609 { 610 return mojoAnnotatedClass.getExecute(); 611 } 612 String parentClassName = mojoAnnotatedClass.getParentClassName(); 613 if ( StringUtils.isEmpty( parentClassName ) ) 614 { 615 return null; 616 } 617 MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); 618 if ( parent == null ) 619 { 620 return null; 621 } 622 return findExecuteInParentHierarchy( parent, mojoAnnotatedClasses ); 623 } 624 625 626 protected Map<String, ParameterAnnotationContent> getParametersParentHierarchy( 627 MojoAnnotatedClass mojoAnnotatedClass, Map<String, ParameterAnnotationContent> parameters, 628 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 629 { 630 List<ParameterAnnotationContent> parameterAnnotationContents = new ArrayList<ParameterAnnotationContent>(); 631 632 parameterAnnotationContents = 633 getParametersParent( mojoAnnotatedClass, parameterAnnotationContents, mojoAnnotatedClasses ); 634 635 // move to parent first to build the Map 636 Collections.reverse( parameterAnnotationContents ); 637 638 Map<String, ParameterAnnotationContent> map = 639 new HashMap<String, ParameterAnnotationContent>( parameterAnnotationContents.size() ); 640 641 for ( ParameterAnnotationContent parameterAnnotationContent : parameterAnnotationContents ) 642 { 643 map.put( parameterAnnotationContent.getFieldName(), parameterAnnotationContent ); 644 } 645 return map; 646 } 647 648 protected List<ParameterAnnotationContent> getParametersParent( MojoAnnotatedClass mojoAnnotatedClass, 649 List<ParameterAnnotationContent> parameterAnnotationContents, 650 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 651 { 652 parameterAnnotationContents.addAll( mojoAnnotatedClass.getParameters().values() ); 653 String parentClassName = mojoAnnotatedClass.getParentClassName(); 654 if ( parentClassName != null ) 655 { 656 MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); 657 if ( parent != null ) 658 { 659 return getParametersParent( parent, parameterAnnotationContents, mojoAnnotatedClasses ); 660 } 661 } 662 return parameterAnnotationContents; 663 } 664 665 protected Map<String, ComponentAnnotationContent> getComponentsParentHierarchy( 666 MojoAnnotatedClass mojoAnnotatedClass, Map<String, ComponentAnnotationContent> components, 667 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 668 { 669 List<ComponentAnnotationContent> componentAnnotationContents = new ArrayList<ComponentAnnotationContent>(); 670 671 componentAnnotationContents = 672 getComponentParent( mojoAnnotatedClass, componentAnnotationContents, mojoAnnotatedClasses ); 673 674 // move to parent first to build the Map 675 Collections.reverse( componentAnnotationContents ); 676 677 Map<String, ComponentAnnotationContent> map = 678 new HashMap<String, ComponentAnnotationContent>( componentAnnotationContents.size() ); 679 680 for ( ComponentAnnotationContent componentAnnotationContent : componentAnnotationContents ) 681 { 682 map.put( componentAnnotationContent.getFieldName(), componentAnnotationContent ); 683 } 684 return map; 685 } 686 687 protected List<ComponentAnnotationContent> getComponentParent( MojoAnnotatedClass mojoAnnotatedClass, 688 List<ComponentAnnotationContent> componentAnnotationContents, 689 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses ) 690 { 691 componentAnnotationContents.addAll( mojoAnnotatedClass.getComponents().values() ); 692 String parentClassName = mojoAnnotatedClass.getParentClassName(); 693 if ( parentClassName != null ) 694 { 695 MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName ); 696 if ( parent != null ) 697 { 698 return getComponentParent( parent, componentAnnotationContents, mojoAnnotatedClasses ); 699 } 700 } 701 return componentAnnotationContents; 702 } 703 704 protected MavenProject getFromProjectReferences( Artifact artifact, MavenProject project ) 705 { 706 if ( project.getProjectReferences() == null || project.getProjectReferences().isEmpty() ) 707 { 708 return null; 709 } 710 @SuppressWarnings( "unchecked" ) Collection<MavenProject> mavenProjects = 711 project.getProjectReferences().values(); 712 for ( MavenProject mavenProject : mavenProjects ) 713 { 714 if ( StringUtils.equals( mavenProject.getId(), artifact.getId() ) ) 715 { 716 return mavenProject; 717 } 718 } 719 return null; 720 } 721 722 }