Coverage Report - org.apache.maven.tools.plugin.annotations.JavaAnnotationsMojoDescriptorExtractor
 
Classes in this File Line Coverage Branch Coverage Complexity
JavaAnnotationsMojoDescriptorExtractor
0 %
0/249
0 %
0/130
5,263
 
 1  
 package org.apache.maven.tools.plugin.annotations;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import com.thoughtworks.qdox.JavaDocBuilder;
 23  
 import com.thoughtworks.qdox.model.DocletTag;
 24  
 import com.thoughtworks.qdox.model.JavaClass;
 25  
 import com.thoughtworks.qdox.model.JavaField;
 26  
 import org.apache.maven.artifact.Artifact;
 27  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 28  
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 29  
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 30  
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 31  
 import org.apache.maven.plugin.descriptor.DuplicateParameterException;
 32  
 import org.apache.maven.plugin.descriptor.InvalidParameterException;
 33  
 import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
 34  
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 35  
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 36  
 import org.apache.maven.plugin.descriptor.Requirement;
 37  
 import org.apache.maven.project.MavenProject;
 38  
 import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
 39  
 import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
 40  
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 41  
 import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent;
 42  
 import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent;
 43  
 import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent;
 44  
 import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent;
 45  
 import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotatedClass;
 46  
 import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner;
 47  
 import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScannerRequest;
 48  
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
 49  
 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
 50  
 import org.apache.maven.tools.plugin.util.PluginUtils;
 51  
 import org.codehaus.plexus.archiver.UnArchiver;
 52  
 import org.codehaus.plexus.archiver.manager.ArchiverManager;
 53  
 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
 54  
 import org.codehaus.plexus.component.annotations.Component;
 55  
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 56  
 import org.codehaus.plexus.util.StringUtils;
 57  
 
 58  
 import java.io.File;
 59  
 import java.util.ArrayList;
 60  
 import java.util.Arrays;
 61  
 import java.util.Collection;
 62  
 import java.util.Collections;
 63  
 import java.util.HashMap;
 64  
 import java.util.HashSet;
 65  
 import java.util.List;
 66  
 import java.util.Map;
 67  
 import java.util.Set;
 68  
 import java.util.TreeMap;
 69  
 import java.util.TreeSet;
 70  
 
 71  
 /**
 72  
  * JavaMojoDescriptorExtractor, a MojoDescriptor extractor to read descriptors from java classes with annotations.
 73  
  *
 74  
  * @author Olivier Lamy
 75  
  * @since 3.0
 76  
  */
 77  
 @Component( role = MojoDescriptorExtractor.class, hint = "java-annotations" )
 78  0
 public class JavaAnnotationsMojoDescriptorExtractor
 79  
     extends AbstractLogEnabled
 80  
     implements MojoDescriptorExtractor
 81  
 {
 82  
 
 83  
     @org.codehaus.plexus.component.annotations.Requirement
 84  
     private MojoAnnotationsScanner mojoAnnotationsScanner;
 85  
 
 86  
     @org.codehaus.plexus.component.annotations.Requirement
 87  
     private ArtifactResolver artifactResolver;
 88  
 
 89  
     @org.codehaus.plexus.component.annotations.Requirement
 90  
     private ArtifactFactory artifactFactory;
 91  
 
 92  
     @org.codehaus.plexus.component.annotations.Requirement
 93  
     private ArchiverManager archiverManager;
 94  
 
 95  
     public List<MojoDescriptor> execute( MavenProject project, PluginDescriptor pluginDescriptor )
 96  
         throws ExtractionException, InvalidPluginDescriptorException
 97  
     {
 98  0
         return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) );
 99  
     }
 100  
 
 101  
     public List<MojoDescriptor> execute( PluginToolsRequest request )
 102  
         throws ExtractionException, InvalidPluginDescriptorException
 103  
     {
 104  0
         Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = scanAnnotations( request );
 105  
 
 106  0
         Map<String, JavaClass> javaClassesMap = scanJavadoc( request, mojoAnnotatedClasses.values() );
 107  
 
 108  0
         populateDataFromJavadoc( mojoAnnotatedClasses, javaClassesMap );
 109  
 
 110  0
         return toMojoDescriptors( mojoAnnotatedClasses, request.getPluginDescriptor() );
 111  
     }
 112  
 
 113  
     private Map<String, MojoAnnotatedClass> scanAnnotations( PluginToolsRequest request )
 114  
         throws ExtractionException
 115  
     {
 116  0
         MojoAnnotationsScannerRequest mojoAnnotationsScannerRequest = new MojoAnnotationsScannerRequest();
 117  
 
 118  0
         File output = new File( request.getProject().getBuild().getOutputDirectory() );
 119  0
         mojoAnnotationsScannerRequest.setClassesDirectories( Arrays.asList( output ) );
 120  
 
 121  0
         mojoAnnotationsScannerRequest.setDependencies( request.getDependencies() );
 122  
 
 123  0
         mojoAnnotationsScannerRequest.setProject( request.getProject() );
 124  
 
 125  0
         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  0
         List<MavenProject> mavenProjects = new ArrayList<MavenProject>();
 135  
 
 136  
         // if we need to scan sources from external artifacts
 137  0
         Set<Artifact> externalArtifacts = new HashSet<Artifact>();
 138  
 
 139  0
         for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses )
 140  
         {
 141  0
             if ( StringUtils.equals( mojoAnnotatedClass.getArtifact().getArtifactId(),
 142  
                                      request.getProject().getArtifact().getArtifactId() ) )
 143  
             {
 144  0
                 continue;
 145  
             }
 146  
 
 147  0
             if ( !isMojoAnnnotatedClassCandidate( mojoAnnotatedClass ) )
 148  
             {
 149  
                 // we don't scan sources for classes without mojo annotations
 150  0
                 continue;
 151  
             }
 152  
 
 153  0
             MavenProject mavenProject =
 154  
                 getFromProjectReferences( mojoAnnotatedClass.getArtifact(), request.getProject() );
 155  
 
 156  0
             if ( mavenProject != null )
 157  
             {
 158  0
                 mavenProjects.add( mavenProject );
 159  
             }
 160  
             else
 161  
             {
 162  0
                 externalArtifacts.add( mojoAnnotatedClass.getArtifact() );
 163  
             }
 164  0
         }
 165  
 
 166  0
         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  0
         for ( Artifact artifact : externalArtifacts )
 170  
         {
 171  
             // parameter for test-sources too ?? olamy I need that for it test only
 172  0
             if ( StringUtils.equalsIgnoreCase( "tests", artifact.getClassifier() ) )
 173  
             {
 174  0
                 javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "test-sources" ) );
 175  
             }
 176  
             else
 177  
             {
 178  0
                 javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "sources" ) );
 179  
             }
 180  
 
 181  
         }
 182  
 
 183  0
         for ( MavenProject mavenProject : mavenProjects )
 184  
         {
 185  0
             javaClassesMap.putAll( discoverClasses( request.getEncoding(), mavenProject ) );
 186  
         }
 187  
 
 188  0
         javaClassesMap.putAll( discoverClasses( request ) );
 189  
 
 190  0
         return javaClassesMap;
 191  
     }
 192  
 
 193  
     private boolean isMojoAnnnotatedClassCandidate( MojoAnnotatedClass mojoAnnotatedClass )
 194  
     {
 195  0
         if ( mojoAnnotatedClass == null )
 196  
         {
 197  0
             return false;
 198  
         }
 199  0
         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  0
             Artifact sourcesArtifact =
 211  
                 artifactFactory.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(),
 212  
                                                               artifact.getVersion(), artifact.getType(), classifier );
 213  
 
 214  0
             artifactResolver.resolve( sourcesArtifact, request.getRemoteRepos(), request.getLocal() );
 215  
 
 216  0
             if ( sourcesArtifact.getFile() == null || !sourcesArtifact.getFile().exists() )
 217  
             {
 218  
                 // could not get artifact sources
 219  0
                 return Collections.emptyMap();
 220  
             }
 221  
 
 222  
             // extract sources to target/maven-plugin-plugin-sources/${groupId}/${artifact}/sources
 223  0
             File extractDirectory = new File( request.getProject().getBuild().getDirectory(),
 224  
                                               "maven-plugin-plugin-sources/" + sourcesArtifact.getGroupId() + "/"
 225  
                                                   + sourcesArtifact.getArtifactId() + "/" + sourcesArtifact.getVersion()
 226  
                                                   + "/" + sourcesArtifact.getClassifier() );
 227  0
             extractDirectory.mkdirs();
 228  
 
 229  0
             UnArchiver unArchiver = archiverManager.getUnArchiver( "jar" );
 230  0
             unArchiver.setSourceFile( sourcesArtifact.getFile() );
 231  0
             unArchiver.setDestDirectory( extractDirectory );
 232  0
             unArchiver.extract();
 233  
 
 234  0
             return discoverClasses( request.getEncoding(), Arrays.asList( extractDirectory ) );
 235  
         }
 236  0
         catch ( ArtifactResolutionException e )
 237  
         {
 238  0
             throw new ExtractionException( e.getMessage(), e );
 239  
         }
 240  0
         catch ( ArtifactNotFoundException e )
 241  
         {
 242  
             //throw new ExtractionException( e.getMessage(), e );
 243  0
             getLogger().debug( "skip ArtifactNotFoundException:" + e.getMessage() );
 244  0
             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  0
             return Collections.emptyMap();
 248  
         }
 249  0
         catch ( NoSuchArchiverException e )
 250  
         {
 251  0
             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  0
         for ( Map.Entry<String, MojoAnnotatedClass> entry : mojoAnnotatedClasses.entrySet() )
 266  
         {
 267  0
             JavaClass javaClass = javaClassesMap.get( entry.getKey() );
 268  0
             if ( javaClass == null )
 269  
             {
 270  0
                 continue;
 271  
             }
 272  
 
 273  
             // populate class-level content
 274  0
             MojoAnnotationContent mojoAnnotationContent = entry.getValue().getMojo();
 275  0
             if ( mojoAnnotationContent != null )
 276  
             {
 277  0
                 mojoAnnotationContent.setDescription( javaClass.getComment() );
 278  
 
 279  0
                 DocletTag since = findInClassHierarchy( javaClass, "since" );
 280  0
                 if ( since != null )
 281  
                 {
 282  0
                     mojoAnnotationContent.setSince( since.getValue() );
 283  
                 }
 284  
 
 285  0
                 DocletTag deprecated = findInClassHierarchy( javaClass, "deprecated" );
 286  0
                 if ( deprecated != null )
 287  
                 {
 288  0
                     mojoAnnotationContent.setDeprecated( deprecated.getValue() );
 289  
                 }
 290  
             }
 291  
 
 292  0
             Map<String, JavaField> fieldsMap = extractFieldParameterTags( javaClass, javaClassesMap );
 293  
 
 294  
             // populate parameters
 295  0
             Map<String, ParameterAnnotationContent> parameters =
 296  
                 getParametersParentHierarchy( entry.getValue(), new HashMap<String, ParameterAnnotationContent>(),
 297  
                                               mojoAnnotatedClasses );
 298  0
             for ( Map.Entry<String, ParameterAnnotationContent> parameter : new TreeMap<String, ParameterAnnotationContent>(
 299  
                 parameters ).entrySet() )
 300  
             {
 301  0
                 JavaField javaField = fieldsMap.get( parameter.getKey() );
 302  0
                 if ( javaField == null )
 303  
                 {
 304  0
                     continue;
 305  
                 }
 306  
 
 307  0
                 ParameterAnnotationContent parameterAnnotationContent = parameter.getValue();
 308  0
                 parameterAnnotationContent.setDescription( javaField.getComment() );
 309  
 
 310  0
                 DocletTag deprecated = javaField.getTagByName( "deprecated" );
 311  0
                 if ( deprecated != null )
 312  
                 {
 313  0
                     parameterAnnotationContent.setDeprecated( deprecated.getValue() );
 314  
                 }
 315  
 
 316  0
                 DocletTag since = javaField.getTagByName( "since" );
 317  0
                 if ( since != null )
 318  
                 {
 319  0
                     parameterAnnotationContent.setSince( since.getValue() );
 320  
                 }
 321  0
             }
 322  
 
 323  
             // populate components
 324  0
             for ( Map.Entry<String, ComponentAnnotationContent> component : entry.getValue().getComponents().entrySet() )
 325  
             {
 326  0
                 JavaField javaField = fieldsMap.get( component.getKey() );
 327  0
                 if ( javaField == null )
 328  
                 {
 329  0
                     continue;
 330  
                 }
 331  
 
 332  0
                 ComponentAnnotationContent componentAnnotationContent = component.getValue();
 333  0
                 componentAnnotationContent.setDescription( javaField.getComment() );
 334  
 
 335  0
                 DocletTag deprecated = javaField.getTagByName( "deprecated" );
 336  0
                 if ( deprecated != null )
 337  
                 {
 338  0
                     componentAnnotationContent.setDeprecated( deprecated.getValue() );
 339  
                 }
 340  
 
 341  0
                 DocletTag since = javaField.getTagByName( "since" );
 342  0
                 if ( since != null )
 343  
                 {
 344  0
                     componentAnnotationContent.setSince( since.getValue() );
 345  
                 }
 346  0
             }
 347  
 
 348  0
         }
 349  
 
 350  0
     }
 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  0
         DocletTag tag = javaClass.getTagByName( tagName );
 360  
 
 361  0
         if ( tag == null )
 362  
         {
 363  0
             JavaClass superClass = javaClass.getSuperJavaClass();
 364  
 
 365  0
             if ( superClass != null )
 366  
             {
 367  0
                 tag = findInClassHierarchy( superClass, tagName );
 368  
             }
 369  
         }
 370  
 
 371  0
         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  0
         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  0
         JavaClass superClass = javaClass.getSuperJavaClass();
 388  
 
 389  0
         if ( superClass != null )
 390  
         {
 391  0
             if ( superClass.getFields().length > 0 )
 392  
             {
 393  0
                 rawParams = extractFieldParameterTags( superClass, javaClassesMap );
 394  
             }
 395  
             // maybe sources comes from scan of sources artifact
 396  0
             superClass = javaClassesMap.get( superClass.getFullyQualifiedName() );
 397  0
             if ( superClass != null )
 398  
             {
 399  0
                 rawParams = extractFieldParameterTags( superClass, javaClassesMap );
 400  
             }
 401  
         }
 402  
         else
 403  
         {
 404  
 
 405  0
             rawParams = new TreeMap<String, JavaField>();
 406  
         }
 407  
 
 408  0
         JavaField[] classFields = javaClass.getFields();
 409  
 
 410  0
         if ( classFields != null )
 411  
         {
 412  0
             for ( JavaField field : classFields )
 413  
             {
 414  0
                 rawParams.put( field.getName(), field );
 415  
             }
 416  
         }
 417  0
         return rawParams;
 418  
     }
 419  
 
 420  
     protected Map<String, JavaClass> discoverClasses( final PluginToolsRequest request )
 421  
     {
 422  0
         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  0
         List<File> sources = new ArrayList<File>();
 429  
 
 430  0
         for ( String source : (List<String>) project.getCompileSourceRoots() )
 431  
         {
 432  0
             sources.add( new File( source ) );
 433  
         }
 434  
 
 435  
         // TODO be more dynamic
 436  0
         File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" );
 437  0
         if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() )
 438  
             && generatedPlugin.exists() )
 439  
         {
 440  0
             sources.add( generatedPlugin );
 441  
         }
 442  
 
 443  0
         return discoverClasses( encoding, sources );
 444  
     }
 445  
 
 446  
     protected Map<String, JavaClass> discoverClasses( final String encoding, List<File> sourceDirectories )
 447  
     {
 448  0
         JavaDocBuilder builder = new JavaDocBuilder();
 449  0
         builder.setEncoding( encoding );
 450  
 
 451  0
         for ( File source : sourceDirectories )
 452  
         {
 453  0
             builder.addSourceTree( source );
 454  
         }
 455  
 
 456  0
         JavaClass[] javaClasses = builder.getClasses();
 457  
 
 458  0
         if ( javaClasses == null || javaClasses.length < 1 )
 459  
         {
 460  0
             return Collections.emptyMap();
 461  
         }
 462  
 
 463  0
         Map<String, JavaClass> javaClassMap = new HashMap<String, JavaClass>( javaClasses.length );
 464  
 
 465  0
         for ( JavaClass javaClass : javaClasses )
 466  
         {
 467  0
             javaClassMap.put( javaClass.getFullyQualifiedName(), javaClass );
 468  
         }
 469  
 
 470  0
         return javaClassMap;
 471  
     }
 472  
 
 473  
     private List<MojoDescriptor> toMojoDescriptors( Map<String, MojoAnnotatedClass> mojoAnnotatedClasses,
 474  
                                                     PluginDescriptor pluginDescriptor )
 475  
         throws DuplicateParameterException, InvalidParameterException
 476  
     {
 477  0
         List<MojoDescriptor> mojoDescriptors = new ArrayList<MojoDescriptor>( mojoAnnotatedClasses.size() );
 478  0
         for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses.values() )
 479  
         {
 480  
             // no mojo so skip it
 481  0
             if ( mojoAnnotatedClass.getMojo() == null )
 482  
             {
 483  0
                 continue;
 484  
             }
 485  
 
 486  0
             ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor();
 487  
 
 488  
             //mojoDescriptor.setRole( mojoAnnotatedClass.getClassName() );
 489  
             //mojoDescriptor.setRoleHint( "default" );
 490  0
             mojoDescriptor.setImplementation( mojoAnnotatedClass.getClassName() );
 491  0
             mojoDescriptor.setLanguage( "java" );
 492  
 
 493  0
             MojoAnnotationContent mojo = mojoAnnotatedClass.getMojo();
 494  
 
 495  0
             mojoDescriptor.setDescription( mojo.getDescription() );
 496  0
             mojoDescriptor.setSince( mojo.getSince() );
 497  0
             mojo.setDeprecated( mojo.getDeprecated() );
 498  
 
 499  0
             mojoDescriptor.setProjectRequired( mojo.requiresProject() );
 500  
 
 501  0
             mojoDescriptor.setRequiresReports( mojo.requiresReports() );
 502  
 
 503  0
             mojoDescriptor.setComponentConfigurator( mojo.configurator() );
 504  
 
 505  0
             mojoDescriptor.setInheritedByDefault( mojo.inheritByDefault() );
 506  
 
 507  0
             mojoDescriptor.setInstantiationStrategy( mojo.instantiationStrategy().id() );
 508  
 
 509  0
             mojoDescriptor.setAggregator( mojo.aggregator() );
 510  0
             mojoDescriptor.setDependencyResolutionRequired( mojo.requiresDependencyResolution().id() );
 511  0
             mojoDescriptor.setDependencyCollectionRequired( mojo.requiresDependencyCollection().id() );
 512  
 
 513  0
             mojoDescriptor.setDirectInvocationOnly( mojo.requiresDirectInvocation() );
 514  0
             mojoDescriptor.setDeprecated( mojo.getDeprecated() );
 515  0
             mojoDescriptor.setThreadSafe( mojo.threadSafe() );
 516  
 
 517  0
             ExecuteAnnotationContent execute = findExecuteInParentHierarchy( mojoAnnotatedClass, mojoAnnotatedClasses );
 518  0
             if ( execute != null )
 519  
             {
 520  0
                 mojoDescriptor.setExecuteGoal( execute.goal() );
 521  0
                 mojoDescriptor.setExecuteLifecycle( execute.lifecycle() );
 522  0
                 mojoDescriptor.setExecutePhase( execute.phase().id() );
 523  
             }
 524  
 
 525  0
             mojoDescriptor.setExecutionStrategy( mojo.executionStrategy() );
 526  
             // ???
 527  
             //mojoDescriptor.alwaysExecute(mojo.a)
 528  
 
 529  0
             mojoDescriptor.setGoal( mojo.name() );
 530  0
             mojoDescriptor.setOnlineRequired( mojo.requiresOnline() );
 531  
 
 532  0
             mojoDescriptor.setPhase( mojo.defaultPhase().id() );
 533  
 
 534  0
             Map<String, ParameterAnnotationContent> parameters =
 535  
                 getParametersParentHierarchy( mojoAnnotatedClass, new HashMap<String, ParameterAnnotationContent>(),
 536  
                                               mojoAnnotatedClasses );
 537  
 
 538  0
             for ( ParameterAnnotationContent parameterAnnotationContent : new TreeSet<ParameterAnnotationContent>(
 539  
                 parameters.values() ) )
 540  
             {
 541  0
                 org.apache.maven.plugin.descriptor.Parameter parameter =
 542  
                     new org.apache.maven.plugin.descriptor.Parameter();
 543  0
                 parameter.setName( parameterAnnotationContent.getFieldName() );
 544  0
                 parameter.setAlias( parameterAnnotationContent.alias() );
 545  0
                 parameter.setDefaultValue( parameterAnnotationContent.defaultValue() );
 546  0
                 parameter.setDeprecated( parameterAnnotationContent.getDeprecated() );
 547  0
                 parameter.setDescription( parameterAnnotationContent.getDescription() );
 548  0
                 parameter.setEditable( !parameterAnnotationContent.readonly() );
 549  0
                 String property = parameterAnnotationContent.property();
 550  0
                 if ( StringUtils.contains( property, '$' ) || StringUtils.contains( property, '{' )
 551  
                     || StringUtils.contains( property, '}' ) )
 552  
                 {
 553  0
                     throw new InvalidParameterException(
 554  
                         "Invalid property for parameter '" + parameter.getName() + "', " + "forbidden characters ${}: "
 555  
                             + property, null );
 556  
                 }
 557  0
                 parameter.setExpression( StringUtils.isEmpty( property ) ? "" : "${" + property + "}" );
 558  0
                 parameter.setType( parameterAnnotationContent.getClassName() );
 559  0
                 parameter.setSince( parameterAnnotationContent.getSince() );
 560  0
                 parameter.setRequired( parameterAnnotationContent.required() );
 561  
 
 562  0
                 mojoDescriptor.addParameter( parameter );
 563  0
             }
 564  
 
 565  0
             Map<String, ComponentAnnotationContent> components =
 566  
                 getComponentsParentHierarchy( mojoAnnotatedClass, new HashMap<String, ComponentAnnotationContent>(),
 567  
                                               mojoAnnotatedClasses );
 568  
 
 569  0
             for ( ComponentAnnotationContent componentAnnotationContent : new TreeSet<ComponentAnnotationContent>(
 570  
                 components.values() ) )
 571  
             {
 572  0
                 org.apache.maven.plugin.descriptor.Parameter parameter =
 573  
                     new org.apache.maven.plugin.descriptor.Parameter();
 574  0
                 parameter.setName( componentAnnotationContent.getFieldName() );
 575  
 
 576  0
                 String expression = PluginUtils.MAVEN_COMPONENTS.get( componentAnnotationContent.getRoleClassName() );
 577  0
                 if ( expression == null )
 578  
                 {
 579  0
                     parameter.setRequirement( new Requirement( componentAnnotationContent.getRoleClassName(),
 580  
                                                                componentAnnotationContent.hint() ) );
 581  
                 }
 582  
                 else
 583  
                 {
 584  0
                     parameter.setDefaultValue( expression );
 585  0
                     parameter.setImplementation( componentAnnotationContent.getRoleClassName() );
 586  0
                     parameter.setType( componentAnnotationContent.getRoleClassName() );
 587  
                 }
 588  0
                 parameter.setDeprecated( componentAnnotationContent.getDeprecated() );
 589  0
                 parameter.setSince( componentAnnotationContent.getSince() );
 590  
 
 591  
                 // same behaviour as JavaMojoDescriptorExtractor
 592  
                 //parameter.setRequired( ... );
 593  0
                 parameter.setEditable( false );
 594  0
                 mojoDescriptor.addParameter( parameter );
 595  0
             }
 596  
 
 597  0
             mojoDescriptor.setPluginDescriptor( pluginDescriptor );
 598  
 
 599  0
             mojoDescriptors.add( mojoDescriptor );
 600  0
         }
 601  0
         return mojoDescriptors;
 602  
     }
 603  
 
 604  
     protected ExecuteAnnotationContent findExecuteInParentHierarchy( MojoAnnotatedClass mojoAnnotatedClass,
 605  
                                                                      Map<String, MojoAnnotatedClass> mojoAnnotatedClasses )
 606  
     {
 607  
 
 608  0
         if ( mojoAnnotatedClass.getExecute() != null )
 609  
         {
 610  0
             return mojoAnnotatedClass.getExecute();
 611  
         }
 612  0
         String parentClassName = mojoAnnotatedClass.getParentClassName();
 613  0
         if ( StringUtils.isEmpty( parentClassName ) )
 614  
         {
 615  0
             return null;
 616  
         }
 617  0
         MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName );
 618  0
         if ( parent == null )
 619  
         {
 620  0
             return null;
 621  
         }
 622  0
         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  0
         List<ParameterAnnotationContent> parameterAnnotationContents = new ArrayList<ParameterAnnotationContent>();
 631  
 
 632  0
         parameterAnnotationContents =
 633  
             getParametersParent( mojoAnnotatedClass, parameterAnnotationContents, mojoAnnotatedClasses );
 634  
 
 635  
         // move to parent first to build the Map
 636  0
         Collections.reverse( parameterAnnotationContents );
 637  
 
 638  0
         Map<String, ParameterAnnotationContent> map =
 639  
             new HashMap<String, ParameterAnnotationContent>( parameterAnnotationContents.size() );
 640  
 
 641  0
         for ( ParameterAnnotationContent parameterAnnotationContent : parameterAnnotationContents )
 642  
         {
 643  0
             map.put( parameterAnnotationContent.getFieldName(), parameterAnnotationContent );
 644  
         }
 645  0
         return map;
 646  
     }
 647  
 
 648  
     protected List<ParameterAnnotationContent> getParametersParent( MojoAnnotatedClass mojoAnnotatedClass,
 649  
                                                                     List<ParameterAnnotationContent> parameterAnnotationContents,
 650  
                                                                     Map<String, MojoAnnotatedClass> mojoAnnotatedClasses )
 651  
     {
 652  0
         parameterAnnotationContents.addAll( mojoAnnotatedClass.getParameters().values() );
 653  0
         String parentClassName = mojoAnnotatedClass.getParentClassName();
 654  0
         if ( parentClassName != null )
 655  
         {
 656  0
             MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName );
 657  0
             if ( parent != null )
 658  
             {
 659  0
                 return getParametersParent( parent, parameterAnnotationContents, mojoAnnotatedClasses );
 660  
             }
 661  
         }
 662  0
         return parameterAnnotationContents;
 663  
     }
 664  
 
 665  
     protected Map<String, ComponentAnnotationContent> getComponentsParentHierarchy(
 666  
         MojoAnnotatedClass mojoAnnotatedClass, Map<String, ComponentAnnotationContent> components,
 667  
         Map<String, MojoAnnotatedClass> mojoAnnotatedClasses )
 668  
     {
 669  0
         List<ComponentAnnotationContent> componentAnnotationContents = new ArrayList<ComponentAnnotationContent>();
 670  
 
 671  0
         componentAnnotationContents =
 672  
             getComponentParent( mojoAnnotatedClass, componentAnnotationContents, mojoAnnotatedClasses );
 673  
 
 674  
         // move to parent first to build the Map
 675  0
         Collections.reverse( componentAnnotationContents );
 676  
 
 677  0
         Map<String, ComponentAnnotationContent> map =
 678  
             new HashMap<String, ComponentAnnotationContent>( componentAnnotationContents.size() );
 679  
 
 680  0
         for ( ComponentAnnotationContent componentAnnotationContent : componentAnnotationContents )
 681  
         {
 682  0
             map.put( componentAnnotationContent.getFieldName(), componentAnnotationContent );
 683  
         }
 684  0
         return map;
 685  
     }
 686  
 
 687  
     protected List<ComponentAnnotationContent> getComponentParent( MojoAnnotatedClass mojoAnnotatedClass,
 688  
                                                                    List<ComponentAnnotationContent> componentAnnotationContents,
 689  
                                                                    Map<String, MojoAnnotatedClass> mojoAnnotatedClasses )
 690  
     {
 691  0
         componentAnnotationContents.addAll( mojoAnnotatedClass.getComponents().values() );
 692  0
         String parentClassName = mojoAnnotatedClass.getParentClassName();
 693  0
         if ( parentClassName != null )
 694  
         {
 695  0
             MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName );
 696  0
             if ( parent != null )
 697  
             {
 698  0
                 return getComponentParent( parent, componentAnnotationContents, mojoAnnotatedClasses );
 699  
             }
 700  
         }
 701  0
         return componentAnnotationContents;
 702  
     }
 703  
 
 704  
     protected MavenProject getFromProjectReferences( Artifact artifact, MavenProject project )
 705  
     {
 706  0
         if ( project.getProjectReferences() == null || project.getProjectReferences().isEmpty() )
 707  
         {
 708  0
             return null;
 709  
         }
 710  0
         @SuppressWarnings( "unchecked" ) Collection<MavenProject> mavenProjects =
 711  
             project.getProjectReferences().values();
 712  0
         for ( MavenProject mavenProject : mavenProjects )
 713  
         {
 714  0
             if ( StringUtils.equals( mavenProject.getId(), artifact.getId() ) )
 715  
             {
 716  0
                 return mavenProject;
 717  
             }
 718  
         }
 719  0
         return null;
 720  
     }
 721  
 
 722  
 }