KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > maven > tools > plugin > extractor > java > JavaMojoDescriptorExtractor


1 package org.apache.maven.tools.plugin.extractor.java;
2
3 /*
4  * Copyright 2001-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import com.thoughtworks.qdox.JavaDocBuilder;
20 import com.thoughtworks.qdox.model.DocletTag;
21 import com.thoughtworks.qdox.model.JavaClass;
22 import com.thoughtworks.qdox.model.JavaField;
23 import com.thoughtworks.qdox.model.JavaSource;
24 import org.apache.maven.plugin.descriptor.InvalidParameterException;
25 import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
26 import org.apache.maven.plugin.descriptor.MojoDescriptor;
27 import org.apache.maven.plugin.descriptor.Parameter;
28 import org.apache.maven.plugin.descriptor.PluginDescriptor;
29 import org.apache.maven.plugin.descriptor.Requirement;
30 import org.apache.maven.project.MavenProject;
31 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
32 import org.codehaus.plexus.logging.AbstractLogEnabled;
33 import org.codehaus.plexus.util.StringUtils;
34
35 import java.io.File JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.List JavaDoc;
39 import java.util.Map JavaDoc;
40 import java.util.TreeMap JavaDoc;
41
42
43 /**
44  * @todo add example usage tag that can be shown in the doco
45  * @todo need to add validation directives so that systems embedding maven2 can
46  * get validation directives to help users in IDEs.
47  */

48 public class JavaMojoDescriptorExtractor
49     extends AbstractLogEnabled
50     implements MojoDescriptorExtractor
51 {
52     public static final String JavaDoc MAVEN_PLUGIN_INSTANTIATION = "instantiationStrategy";
53
54     public static final String JavaDoc CONFIGURATOR = "configurator";
55
56     public static final String JavaDoc PARAMETER = "parameter";
57
58     public static final String JavaDoc PARAMETER_EXPRESSION = "expression";
59
60     public static final String JavaDoc PARAMETER_DEFAULT_VALUE = "default-value";
61
62     /**
63      * This indicates the base name of the bean properties used to read/write this parameter's value.
64      * So:
65      *
66      * @parameter property="project"
67      *
68      * Would say there is a getProject() method and a setProject(Project) method. Here the field
69      * name would not be the basis for the parameter's name. This mode of operation will allow the
70      * mojos to be usable as beans and will be the promoted form of use.
71      */

72     public static final String JavaDoc PARAMETER_PROPERTY = "property";
73
74     public static final String JavaDoc REQUIRED = "required";
75
76     public static final String JavaDoc DEPRECATED = "deprecated";
77
78     public static final String JavaDoc READONLY = "readonly";
79
80     public static final String JavaDoc GOAL = "goal";
81
82     public static final String JavaDoc PHASE = "phase";
83
84     public static final String JavaDoc EXECUTE = "execute";
85
86     public static final String JavaDoc GOAL_DESCRIPTION = "description";
87
88     public static final String JavaDoc GOAL_REQUIRES_DEPENDENCY_RESOLUTION = "requiresDependencyResolution";
89
90     public static final String JavaDoc GOAL_REQUIRES_PROJECT = "requiresProject";
91
92     public static final String JavaDoc GOAL_REQUIRES_REPORTS = "requiresReports";
93
94     public static final String JavaDoc GOAL_IS_AGGREGATOR = "aggregator";
95
96     public static final String JavaDoc GOAL_REQUIRES_ONLINE = "requiresOnline";
97
98     public static final String JavaDoc GOAL_INHERIT_BY_DEFAULT = "inheritByDefault";
99
100     public static final String JavaDoc GOAL_MULTI_EXECUTION_STRATEGY = "attainAlways";
101
102     public static final String JavaDoc GOAL_REQUIRES_DIRECT_INVOCATION = "requiresDirectInvocation";
103
104     private static final String JavaDoc COMPONENT = "component";
105
106     protected void validateParameter( Parameter parameter, int i )
107         throws InvalidParameterException
108     {
109         // TODO: remove when backward compatibility is no longer an issue.
110
String JavaDoc name = parameter.getName();
111
112         if ( name == null )
113         {
114             throw new InvalidParameterException( "name", i );
115         }
116
117         // TODO: remove when backward compatibility is no longer an issue.
118
String JavaDoc type = parameter.getType();
119
120         if ( type == null )
121         {
122             throw new InvalidParameterException( "type", i );
123         }
124
125         // TODO: remove when backward compatibility is no longer an issue.
126
String JavaDoc description = parameter.getDescription();
127
128         if ( description == null )
129         {
130             throw new InvalidParameterException( "description", i );
131         }
132     }
133
134     // ----------------------------------------------------------------------
135
// Mojo descriptor creation from @tags
136
// ----------------------------------------------------------------------
137

138     private MojoDescriptor createMojoDescriptor( JavaSource javaSource, PluginDescriptor pluginDescriptor )
139         throws InvalidPluginDescriptorException
140     {
141         MojoDescriptor mojoDescriptor = new MojoDescriptor();
142
143         mojoDescriptor.setPluginDescriptor( pluginDescriptor );
144
145         JavaClass javaClass = getJavaClass( javaSource );
146
147         mojoDescriptor.setLanguage( "java" );
148
149         mojoDescriptor.setImplementation( javaClass.getFullyQualifiedName() );
150
151         mojoDescriptor.setDescription( javaClass.getComment() );
152
153         DocletTag tag = findInClassHierarchy( javaClass, MAVEN_PLUGIN_INSTANTIATION );
154
155         if ( tag != null )
156         {
157             mojoDescriptor.setInstantiationStrategy( tag.getValue() );
158         }
159
160         tag = findInClassHierarchy( javaClass, GOAL_MULTI_EXECUTION_STRATEGY );
161
162         if ( tag != null )
163         {
164             mojoDescriptor.setExecutionStrategy( MojoDescriptor.MULTI_PASS_EXEC_STRATEGY );
165         }
166         else
167         {
168             mojoDescriptor.setExecutionStrategy( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY );
169         }
170
171         // ----------------------------------------------------------------------
172
// Configurator hint
173
// ----------------------------------------------------------------------
174

175         DocletTag configurator = findInClassHierarchy( javaClass, CONFIGURATOR );
176
177         if ( configurator != null )
178         {
179             mojoDescriptor.setComponentConfigurator( configurator.getValue() );
180         }
181
182         // ----------------------------------------------------------------------
183
// Goal name
184
// ----------------------------------------------------------------------
185

186         DocletTag goal = findInClassHierarchy( javaClass, GOAL );
187
188         if ( goal != null )
189         {
190             mojoDescriptor.setGoal( goal.getValue() );
191         }
192
193         // ----------------------------------------------------------------------
194
// Phase name
195
// ----------------------------------------------------------------------
196

197         DocletTag phase = findInClassHierarchy( javaClass, PHASE );
198
199         if ( phase != null )
200         {
201             mojoDescriptor.setPhase( phase.getValue() );
202         }
203
204         // ----------------------------------------------------------------------
205
// Additional phase to execute first
206
// ----------------------------------------------------------------------
207

208         DocletTag execute = findInClassHierarchy( javaClass, EXECUTE );
209
210         if ( execute != null )
211         {
212             String JavaDoc executePhase = execute.getNamedParameter( "phase" );
213             String JavaDoc executeGoal = execute.getNamedParameter( "goal" );
214
215             if ( executePhase == null && executeGoal == null )
216             {
217                 throw new InvalidPluginDescriptorException( "@execute tag requires a 'phase' or 'goal' parameter" );
218             }
219             else if ( executePhase != null && executeGoal != null )
220             {
221                 throw new InvalidPluginDescriptorException(
222                     "@execute tag can have only one of a 'phase' or 'goal' parameter" );
223             }
224             mojoDescriptor.setExecutePhase( executePhase );
225             mojoDescriptor.setExecuteGoal( executeGoal );
226
227             String JavaDoc lifecycle = execute.getNamedParameter( "lifecycle" );
228
229             if ( lifecycle != null )
230             {
231                 mojoDescriptor.setExecuteLifecycle( lifecycle );
232                 if ( mojoDescriptor.getExecuteGoal() != null )
233                 {
234                     throw new InvalidPluginDescriptorException(
235                         "@execute lifecycle requires a phase instead of a goal" );
236                 }
237             }
238         }
239
240         // ----------------------------------------------------------------------
241
// Dependency resolution flag
242
// ----------------------------------------------------------------------
243

244         DocletTag requiresDependencyResolution = findInClassHierarchy( javaClass, GOAL_REQUIRES_DEPENDENCY_RESOLUTION );
245
246         if ( requiresDependencyResolution != null )
247         {
248             String JavaDoc value = requiresDependencyResolution.getValue();
249
250             if ( value == null || value.length() == 0 )
251             {
252                 value = "runtime";
253             }
254
255             mojoDescriptor.setDependencyResolutionRequired( value );
256         }
257
258         // ----------------------------------------------------------------------
259
// Project flag
260
// ----------------------------------------------------------------------
261

262         boolean value = getBooleanTagValue( javaClass, GOAL_REQUIRES_PROJECT, mojoDescriptor.isProjectRequired() );
263         mojoDescriptor.setProjectRequired( value );
264
265         // ----------------------------------------------------------------------
266
// Aggregator flag
267
// ----------------------------------------------------------------------
268

269         DocletTag aggregator = findInClassHierarchy( javaClass, GOAL_IS_AGGREGATOR );
270
271         if ( aggregator != null )
272         {
273             mojoDescriptor.setAggregator( true );
274         }
275
276         // ----------------------------------------------------------------------
277
// requiresDirectInvocation flag
278
// ----------------------------------------------------------------------
279

280         value = getBooleanTagValue( javaClass, GOAL_REQUIRES_DIRECT_INVOCATION,
281                                     mojoDescriptor.isDirectInvocationOnly() );
282         mojoDescriptor.setDirectInvocationOnly( value );
283
284         // ----------------------------------------------------------------------
285
// Online flag
286
// ----------------------------------------------------------------------
287

288         value = getBooleanTagValue( javaClass, GOAL_REQUIRES_ONLINE, mojoDescriptor.isOnlineRequired() );
289         mojoDescriptor.setOnlineRequired( value );
290
291         // ----------------------------------------------------------------------
292
// inheritByDefault flag
293
// ----------------------------------------------------------------------
294

295         value = getBooleanTagValue( javaClass, GOAL_INHERIT_BY_DEFAULT, mojoDescriptor.isInheritedByDefault() );
296         mojoDescriptor.setInheritedByDefault( value );
297
298         extractParameters( mojoDescriptor, javaClass );
299
300         return mojoDescriptor;
301     }
302
303     private static boolean getBooleanTagValue( JavaClass javaClass, String JavaDoc tagName, boolean defaultValue )
304     {
305         DocletTag requiresProject = findInClassHierarchy( javaClass, tagName );
306
307         if ( requiresProject != null )
308         {
309             String JavaDoc requiresProjectValue = requiresProject.getValue();
310
311             if ( requiresProjectValue != null && requiresProjectValue.length() > 0 )
312             {
313                 defaultValue = Boolean.valueOf( requiresProjectValue ).booleanValue();
314             }
315         }
316         return defaultValue;
317     }
318
319     private static DocletTag findInClassHierarchy( JavaClass javaClass, String JavaDoc tagName )
320     {
321         DocletTag tag = javaClass.getTagByName( tagName );
322
323         if ( tag == null )
324         {
325             JavaClass superClass = javaClass.getSuperJavaClass();
326
327             if ( superClass != null )
328             {
329                 tag = findInClassHierarchy( superClass, tagName );
330             }
331         }
332
333         return tag;
334     }
335
336     private void extractParameters( MojoDescriptor mojoDescriptor, JavaClass javaClass )
337         throws InvalidPluginDescriptorException
338     {
339         // ---------------------------------------------------------------------------------
340
// We're resolving class-level, ancestor-class-field, local-class-field order here.
341
// ---------------------------------------------------------------------------------
342

343         Map JavaDoc rawParams = extractFieldParameterTags( javaClass );
344
345         for ( Iterator JavaDoc it = rawParams.entrySet().iterator(); it.hasNext(); )
346         {
347             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
348
349             JavaField field = (JavaField) entry.getValue();
350
351             Parameter pd = new Parameter();
352
353             pd.setType( field.getType().getValue() );
354
355             pd.setDescription( field.getComment() );
356
357             DocletTag componentTag = field.getTagByName( COMPONENT );
358
359             if ( componentTag != null )
360             {
361                 String JavaDoc role = componentTag.getNamedParameter( "role" );
362
363                 if ( role == null )
364                 {
365                     role = field.getType().toString();
366                 }
367
368                 String JavaDoc roleHint = componentTag.getNamedParameter( "roleHint" );
369
370                 pd.setRequirement( new Requirement( role, roleHint ) );
371
372                 pd.setName( (String JavaDoc) entry.getKey() );
373             }
374             else
375             {
376                 DocletTag parameter = field.getTagByName( PARAMETER );
377
378                 // ----------------------------------------------------------------------
379
// We will look for a property name here first and use that if present
380
// i.e:
381
//
382
// @parameter property="project"
383
//
384
// Which will become the name used for the configuration element which
385
// will in turn will allow plexus to use the corresponding setter.
386
// ----------------------------------------------------------------------
387

388                 String JavaDoc property = parameter.getNamedParameter( PARAMETER_PROPERTY );
389
390                 if ( !StringUtils.isEmpty( property ) )
391                 {
392                     pd.setName( property );
393                 }
394                 else
395                 {
396                     pd.setName( (String JavaDoc) entry.getKey() );
397                 }
398
399                 pd.setRequired( field.getTagByName( REQUIRED ) != null );
400
401                 pd.setEditable( field.getTagByName( READONLY ) == null );
402
403                 DocletTag deprecationTag = field.getTagByName( DEPRECATED );
404
405                 if ( deprecationTag != null )
406                 {
407                     pd.setDeprecated( deprecationTag.getValue() );
408                 }
409
410                 String JavaDoc alias = parameter.getNamedParameter( "alias" );
411
412                 if ( !StringUtils.isEmpty( alias ) )
413                 {
414                     pd.setAlias( alias );
415                 }
416
417                 pd.setExpression( parameter.getNamedParameter( PARAMETER_EXPRESSION ) );
418
419                 if ( "${reports}".equals( pd.getExpression() ) )
420                 {
421                     mojoDescriptor.setRequiresReports( true );
422                 }
423
424                 pd.setDefaultValue( parameter.getNamedParameter( PARAMETER_DEFAULT_VALUE ) );
425             }
426
427             mojoDescriptor.addParameter( pd );
428         }
429     }
430
431     private Map JavaDoc extractFieldParameterTags( JavaClass javaClass )
432     {
433         Map JavaDoc rawParams;
434
435         // we have to add the parent fields first, so that they will be overwritten by the local fields if
436
// that actually happens...
437
JavaClass superClass = javaClass.getSuperJavaClass();
438
439         if ( superClass != null )
440         {
441             rawParams = extractFieldParameterTags( superClass );
442         }
443         else
444         {
445             rawParams = new TreeMap JavaDoc();
446         }
447
448         JavaField[] classFields = javaClass.getFields();
449
450         if ( classFields != null )
451         {
452             for ( int i = 0; i < classFields.length; i++ )
453             {
454                 JavaField field = classFields[i];
455
456                 if ( field.getTagByName( PARAMETER ) != null || field.getTagByName( COMPONENT ) != null )
457                 {
458                     rawParams.put( field.getName(), field );
459                 }
460             }
461         }
462         return rawParams;
463     }
464
465     private JavaClass getJavaClass( JavaSource javaSource )
466     {
467         return javaSource.getClasses()[0];
468     }
469
470     public List JavaDoc execute( MavenProject project, PluginDescriptor pluginDescriptor )
471         throws InvalidPluginDescriptorException
472     {
473         JavaDocBuilder builder = new JavaDocBuilder();
474
475         for ( Iterator JavaDoc i = project.getCompileSourceRoots().iterator(); i.hasNext(); )
476         {
477             builder.addSourceTree( new File JavaDoc( (String JavaDoc) i.next() ) );
478         }
479
480         JavaSource[] javaSources = builder.getSources();
481
482         List JavaDoc descriptors = new ArrayList JavaDoc();
483
484         for ( int i = 0; i < javaSources.length; i++ )
485         {
486             JavaClass javaClass = getJavaClass( javaSources[i] );
487
488             DocletTag tag = javaClass.getTagByName( GOAL );
489
490             if ( tag != null )
491             {
492                 MojoDescriptor mojoDescriptor = createMojoDescriptor( javaSources[i], pluginDescriptor );
493
494                 // ----------------------------------------------------------------------
495
// Validate the descriptor as best we can before allowing it
496
// to be processed.
497
// ----------------------------------------------------------------------
498

499                 List JavaDoc parameters = mojoDescriptor.getParameters();
500
501                 if ( parameters != null )
502                 {
503                     for ( int j = 0; j < parameters.size(); j++ )
504                     {
505                         validateParameter( (Parameter) parameters.get( j ), j );
506                     }
507                 }
508
509                 // Commented because it causes a VerifyError:
510
// java.lang.VerifyError:
511
// (class:
512
// org/apache/maven/tools/plugin/extractor/java/JavaMojoDescriptorExtractor,
513
// method: execute signature:
514
// (Ljava/lang/String;Lorg/apache/maven/project/MavenProject;)Ljava/util/Set;)
515
// Incompatible object argument for function call
516
//
517
// Refactored to allow MavenMojoDescriptor.getComponentFactory()
518
// return MavenMojoDescriptor.getMojoDescriptor().getLanguage(),
519
// and removed all usage of MavenMojoDescriptor from extractors.
520
//
521
//
522
// MavenMojoDescriptor mmDescriptor = new
523
// MavenMojoDescriptor(mojoDescriptor);
524
//
525
// JavaClass javaClass = getJavaClass(javaSources[i]);
526
//
527
// mmDescriptor.setImplementation(javaClass.getFullyQualifiedName());
528
//
529
// descriptors.add( mmDescriptor );
530

531                 descriptors.add( mojoDescriptor );
532             }
533         }
534
535         return descriptors;
536     }
537
538 }
539
Popular Tags