View Javadoc

1   package org.apache.maven.tools.plugin.generator;
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 org.apache.maven.plugin.descriptor.MojoDescriptor;
23  import org.apache.maven.plugin.descriptor.Parameter;
24  import org.apache.maven.plugin.descriptor.PluginDescriptor;
25  import org.codehaus.plexus.util.IOUtil;
26  import org.codehaus.plexus.util.StringUtils;
27  import org.codehaus.plexus.util.xml.XMLWriter;
28  
29  import java.io.File;
30  import java.io.FileWriter;
31  import java.io.IOException;
32  import java.util.ArrayList;
33  import java.util.Iterator;
34  import java.util.List;
35  
36  /**
37   * @todo add example usage tag that can be shown in the doco
38   */
39  public class PluginXdocGenerator
40      implements Generator
41  {
42  
43      public void execute( File destinationDirectory, PluginDescriptor pluginDescriptor )
44          throws IOException
45      {
46          for ( Iterator it = pluginDescriptor.getMojos().iterator(); it.hasNext(); )
47          {
48              MojoDescriptor descriptor = (MojoDescriptor) it.next();
49              processMojoDescriptor( descriptor, destinationDirectory );
50          }
51      }
52  
53      protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, File destinationDirectory )
54          throws IOException
55      {
56          FileWriter writer = null;
57          try
58          {
59              writer = new FileWriter( new File( destinationDirectory, getMojoFilename( mojoDescriptor, "xml" ) ) );
60  
61              writeBody( writer, mojoDescriptor );
62  
63              writer.flush();
64          }
65          finally
66          {
67              IOUtil.close( writer );
68          }
69      }
70  
71      private String getMojoFilename( MojoDescriptor mojo, String ext )
72      {
73          return mojo.getGoal() + "-mojo." + ext;
74      }
75  
76      private void writeBody( FileWriter writer, MojoDescriptor mojoDescriptor )
77      {
78          XMLWriter w = new PrettyPrintXMLWriter( writer );
79  
80          w.startElement( "document" );
81  
82          // ----------------------------------------------------------------------
83          //
84          // ----------------------------------------------------------------------
85  
86          w.startElement( "properties" );
87  
88          w.startElement( "title" );
89  
90          // TODO: need a friendly name for a plugin
91          w.writeText( mojoDescriptor.getPluginDescriptor().getArtifactId() + " - " + mojoDescriptor.getFullGoalName() );
92  
93          w.endElement(); // title
94  
95          w.endElement(); // properties
96  
97          // ----------------------------------------------------------------------
98          //
99          // ----------------------------------------------------------------------
100 
101         w.startElement( "body" );
102 
103         w.startElement( "section" );
104 
105         w.addAttribute( "name", mojoDescriptor.getFullGoalName() );
106 
107         w.startElement( "p" );
108 
109         if ( mojoDescriptor.getDescription() != null )
110         {
111             w.writeMarkup( mojoDescriptor.getDescription() );
112         }
113         else
114         {
115             w.writeText( "No description." );
116         }
117 
118         w.endElement(); // p
119 
120         writeGoalAttributes( mojoDescriptor, w );
121 
122         writeGoalParameterTable( mojoDescriptor, w );
123 
124         w.endElement(); // section
125 
126         w.endElement(); // body
127 
128         w.endElement(); // document
129     }
130 
131     private void writeGoalAttributes( MojoDescriptor mojoDescriptor, XMLWriter w )
132     {
133         w.startElement( "p" );
134         w.writeMarkup( "<b>Mojo Attributes</b>:" );
135         w.startElement( "ul" );
136 
137         String value = mojoDescriptor.getDeprecated();
138         if ( StringUtils.isNotEmpty( value ) )
139         {
140             w.startElement( "li" );
141             w.writeMarkup( "This plugin goal has been deprecated: " + value + "" );
142             w.endElement(); //li
143         }
144 
145         if ( mojoDescriptor.isProjectRequired() )
146         {
147             w.startElement( "li" );
148             w.writeMarkup( "Requires a Maven 2.0 project to execute." );
149             w.endElement(); //li
150         }
151 
152         if ( mojoDescriptor.isAggregator() )
153         {
154             w.startElement( "li" );
155             w.writeMarkup( "Executes as an aggregator plugin." );
156             w.endElement(); //li
157         }
158 
159         if ( mojoDescriptor.isDirectInvocationOnly() )
160         {
161             w.startElement( "li" );
162             w.writeMarkup( "Executes by direct invocation only." );
163             w.endElement(); //li
164         }
165 
166         value = mojoDescriptor.isDependencyResolutionRequired();
167         if ( StringUtils.isNotEmpty( value ) )
168         {
169             w.startElement( "li" );
170             w.writeMarkup( "Requires dependency resolution of artifacts in scope: <code>" + value + "</code>" );
171             w.endElement(); //li
172         }
173 
174         value = mojoDescriptor.getPhase();
175         if ( StringUtils.isNotEmpty( value ) )
176         {
177             w.startElement( "li" );
178             w.writeMarkup( "Automatically executes within the lifecycle phase: <code>" + value + "</code>" );
179             w.endElement(); //li
180         }
181 
182         value = mojoDescriptor.getExecutePhase();
183         if ( StringUtils.isNotEmpty( value ) )
184         {
185             w.startElement( "li" );
186             w.writeMarkup(
187                 "Invokes the execution of the lifecycle phase <code>" + value + "</code> prior to executing itself." );
188             w.endElement(); //li
189         }
190 
191         value = mojoDescriptor.getExecuteGoal();
192         if ( StringUtils.isNotEmpty( value ) )
193         {
194             w.startElement( "li" );
195             w.writeMarkup(
196                 "Invokes the execution of this plugin's goal <code>" + value + "</code> prior to executing itself." );
197             w.endElement(); //li
198         }
199 
200         value = mojoDescriptor.getExecuteLifecycle();
201         if ( StringUtils.isNotEmpty( value ) )
202         {
203             w.startElement( "li" );
204             w.writeMarkup( "Executes in its own lifecycle: <code>" + value + "</code>" );
205             w.endElement(); //li
206         }
207 
208         if ( mojoDescriptor.isOnlineRequired() )
209         {
210             w.startElement( "li" );
211             w.writeMarkup( "Requires that mvn runs in online mode." );
212             w.endElement(); //li
213         }
214 
215         if ( !mojoDescriptor.isInheritedByDefault() )
216         {
217             w.startElement( "li" );
218             w.writeMarkup( "Is NOT inherited by default in multi-project builds." );
219             w.endElement(); //li
220         }
221 
222         w.endElement();//ul
223         w.endElement();//p
224     }
225 
226     private void writeGoalParameterTable( MojoDescriptor mojoDescriptor, XMLWriter w )
227     {
228         List parameterList = mojoDescriptor.getParameters();
229 
230         //remove components and read-only parameters
231         List list = filterParameters( parameterList );
232 
233         if ( list != null && list.size() > 0 )
234         {
235             writeParameterSummary( list, w );
236 
237             writeParameterDetails( list, w );
238         }
239     }
240 
241     private List filterParameters( List parameterList )
242     {
243         List filtered = new ArrayList();
244 
245         for ( Iterator parameters = parameterList.iterator(); parameters.hasNext(); )
246         {
247             Parameter parameter = (Parameter) parameters.next();
248 
249             if ( parameter.isEditable() )
250             {
251                 String expression = parameter.getExpression();
252 
253                 if ( expression == null || !expression.startsWith( "${component." ) )
254                 {
255                     filtered.add( parameter );
256                 }
257             }
258         }
259 
260         return filtered;
261     }
262 
263     private void writeParameterDetails( List parameterList, XMLWriter w )
264     {
265         w.startElement( "subsection" );
266         w.addAttribute( "name", "Parameter Details" );
267 
268         for ( Iterator parameters = parameterList.iterator(); parameters.hasNext(); )
269         {
270             Parameter parameter = (Parameter) parameters.next();
271 
272             w.startElement( "p" );
273             w.writeMarkup( "<b><a name=\"" + parameter.getName() + "\">" + parameter.getName() + "</a></b>" );
274             w.endElement(); //p
275 
276             String description = parameter.getDescription();
277             if ( StringUtils.isEmpty( description ) )
278             {
279                 description = "No Description.";
280             }
281             w.startElement( "p" );
282             w.writeMarkup( description );
283             w.endElement(); //p
284 
285             w.startElement( "ul" );
286 
287             writeDetail( "Type", parameter.getType(), w );
288 
289             if ( parameter.isRequired() )
290             {
291                 writeDetail( "Required", "Yes", w );
292             }
293             else
294             {
295                 writeDetail( "Required", "No", w );
296             }
297 
298             writeDetail( "Expression", parameter.getExpression(), w );
299 
300             writeDetail( "Default", parameter.getDefaultValue(), w );
301 
302             w.endElement();//ul
303 
304             if ( parameters.hasNext() )
305             {
306                 w.writeMarkup( "<hr/>" );
307             }
308         }
309 
310         w.endElement();
311     }
312 
313     private void writeDetail( String param, String value, XMLWriter w )
314     {
315         if ( StringUtils.isNotEmpty( value ) )
316         {
317             w.startElement( "li" );
318             w.writeMarkup( "<b>" + param + "</b>: <code>" );
319             w.writeText( value );
320             w.writeMarkup( "</code>" );
321             w.endElement(); //li
322         }
323     }
324 
325     private void writeParameterSummary( List parameterList, XMLWriter w )
326     {
327         List requiredParams = getParametersByRequired( true, parameterList );
328         if ( requiredParams.size() > 0 )
329         {
330             writeParameterList( "Required Parameters", requiredParams, w );
331         }
332 
333         List optionalParams = getParametersByRequired( false, parameterList );
334         if ( optionalParams.size() > 0 )
335         {
336             writeParameterList( "Optional Parameters", optionalParams, w );
337         }
338     }
339 
340     private void writeParameterList( String title, List parameterList, XMLWriter w )
341     {
342         w.startElement( "subsection" );
343         w.addAttribute( "name", title );
344 
345         w.startElement( "table" );
346 
347         w.startElement( "tr" );
348         w.startElement( "th" );
349         w.writeText( "Name" );
350         w.endElement();//th
351         w.startElement( "th" );
352         w.writeText( "Type" );
353         w.endElement();//th
354         w.startElement( "th" );
355         w.writeText( "Description" );
356         w.endElement();//th
357         w.endElement();//tr
358 
359         for ( Iterator parameters = parameterList.iterator(); parameters.hasNext(); )
360         {
361             Parameter parameter = (Parameter) parameters.next();
362 
363             w.startElement( "tr" );
364             w.startElement( "td" );
365             w.writeMarkup( "<b><a href=\"#" + parameter.getName() + "\">" + parameter.getName() + "</a></b>" );
366             w.endElement();//td
367             w.startElement( "td" );
368             int index = parameter.getType().lastIndexOf( "." );
369             w.writeMarkup( "<code>" + parameter.getType().substring( index + 1 ) + "</code>" );
370             w.endElement();//td
371             w.startElement( "td" );
372             String description = parameter.getDescription();
373             if ( StringUtils.isEmpty( description ) )
374             {
375                 description = "No description.";
376             }
377             w.writeMarkup( description );
378 
379             if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) )
380             {
381                 w.writeMarkup( " Default value is <code>" );
382                 w.writeText( parameter.getDefaultValue() );
383                 w.writeMarkup( "</code>." );
384             }
385             w.endElement();//td
386             w.endElement(); //tr
387         }
388 
389         w.endElement();//table
390         w.endElement();//section
391     }
392 
393     private List getParametersByRequired( boolean required, List parameterList )
394     {
395         List list = new ArrayList();
396 
397         for ( Iterator parameters = parameterList.iterator(); parameters.hasNext(); )
398         {
399             Parameter parameter = (Parameter) parameters.next();
400 
401             if ( parameter.isRequired() == required )
402             {
403                 list.add( parameter );
404             }
405         }
406 
407         return list;
408     }
409 }
410