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