View Javadoc
1   package org.apache.maven.plugin.plugin;
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.artifact.Artifact;
23  import org.apache.maven.artifact.repository.ArtifactRepository;
24  import org.apache.maven.doxia.sink.Sink;
25  import org.apache.maven.doxia.siterenderer.Renderer;
26  import org.apache.maven.model.Plugin;
27  import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
28  import org.apache.maven.plugin.descriptor.MojoDescriptor;
29  import org.apache.maven.plugin.descriptor.PluginDescriptor;
30  import org.apache.maven.plugins.annotations.Component;
31  import org.apache.maven.plugins.annotations.Execute;
32  import org.apache.maven.plugins.annotations.LifecyclePhase;
33  import org.apache.maven.plugins.annotations.Mojo;
34  import org.apache.maven.plugins.annotations.Parameter;
35  import org.apache.maven.project.MavenProject;
36  import org.apache.maven.reporting.AbstractMavenReport;
37  import org.apache.maven.reporting.AbstractMavenReportRenderer;
38  import org.apache.maven.reporting.MavenReportException;
39  import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
40  import org.apache.maven.tools.plugin.PluginToolsRequest;
41  import org.apache.maven.tools.plugin.extractor.ExtractionException;
42  import org.apache.maven.tools.plugin.generator.GeneratorException;
43  import org.apache.maven.tools.plugin.generator.GeneratorUtils;
44  import org.apache.maven.tools.plugin.generator.PluginXdocGenerator;
45  import org.apache.maven.tools.plugin.scanner.MojoScanner;
46  import org.apache.maven.tools.plugin.util.PluginUtils;
47  import org.codehaus.plexus.component.repository.ComponentDependency;
48  import org.codehaus.plexus.util.StringUtils;
49  import org.codehaus.plexus.util.xml.Xpp3Dom;
50  
51  import java.io.File;
52  import java.util.ArrayList;
53  import java.util.Iterator;
54  import java.util.List;
55  import java.util.Locale;
56  import java.util.Map;
57  import java.util.ResourceBundle;
58  import java.util.Set;
59  
60  /**
61   * Generates the Plugin's documentation report: <code>plugin-info.html</code> plugin overview page,
62   * and one <code><i>goal</i>-mojo.html</code> per goal.
63   *
64   * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
65   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
66   * @version $Id: PluginReport.html 934731 2015-01-01 22:17:21Z hboutemy $
67   * @since 2.0
68   */
69  @Mojo( name = "report", threadSafe = true )
70  @Execute( phase = LifecyclePhase.PROCESS_CLASSES )
71  public class PluginReport
72      extends AbstractMavenReport
73  {
74      /**
75       * Report output directory for mojos' documentation.
76       */
77      @Parameter( defaultValue = "${project.build.directory}/generated-site/xdoc" )
78      private File outputDirectory;
79  
80      /**
81       * Doxia Site Renderer.
82       */
83      @Component
84      private Renderer siteRenderer;
85  
86      /**
87       * The Maven Project.
88       */
89      @Parameter( defaultValue = "${project}", readonly = true )
90      private MavenProject project;
91  
92      /**
93       * Mojo scanner tools.
94       */
95      @Component
96      protected MojoScanner mojoScanner;
97  
98      /**
99       * The file encoding of the source files.
100      *
101      * @since 2.7
102      */
103     @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
104     private String encoding;
105 
106     /**
107      * Specify some requirements to execute this plugin.
108      * Example:
109      * <pre>
110      * &lt;requirements&gt;
111      *   &lt;maven&gt;2.0&lt;/maven&gt;
112      *   &lt;jdk&gt;1.4&lt;/jdk&gt;
113      *   &lt;memory&gt;256m&lt;/memory&gt;
114      *   &lt;diskSpace&gt;1m&lt;/diskSpace&gt;
115      *   &lt;others&gt;
116      *     &lt;property&gt;
117      *       &lt;name&gt;SVN&lt;/name&gt;
118      *       &lt;value&gt;1.4.6&lt;/value&gt;
119      *     &lt;/property&gt;
120      *   &lt;/others&gt;
121      * &lt;/requirements&gt;
122      * </pre>
123      */
124     @Parameter
125     private Requirements requirements;
126 
127     /**
128      * The goal prefix that will appear before the ":".
129      * By default, this plugin applies a heuristic to derive a heuristic from
130      * the plugin's artifactId.
131      * <p/>
132      * It removes any occurrences of the regular expression <strong>-?maven-?</strong>,
133      * and then removes any occurrences of <strong>-?plugin-?</strong>.
134      * <p>
135      * For example, horsefeature-maven-plugin becomes horsefeature.
136      * </p>
137      * <p>
138      * (There is a special for maven-plugin-plugin; it is mapped to 'plugin'.
139      * </p>
140      *
141      * @since 2.4
142      */
143     @Parameter( property = "goalPrefix" )
144     protected String goalPrefix;
145 
146     /**
147      * Set this to "true" to skip invoking any goals or reports of the plugin.
148      *
149      * @since 2.8
150      */
151     @Parameter( defaultValue = "false", property = "maven.plugin.skip" )
152     private boolean skip;
153 
154     /**
155      * Set this to "true" to skip generating the report.
156      *
157      * @since 2.8
158      */
159     @Parameter( defaultValue = "false", property = "maven.plugin.report.skip" )
160     private boolean skipReport;
161 
162     /**
163      * The set of dependencies for the current project
164      *
165      * @since 3.0
166      */
167     @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true )
168     protected Set<Artifact> dependencies;
169 
170     /**
171      * List of Remote Repositories used by the resolver
172      *
173      * @since 3.0
174      */
175     @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
176     protected List<ArtifactRepository> remoteRepos;
177 
178     /**
179      * Location of the local repository.
180      *
181      * @since 3.0
182      */
183     @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
184     protected ArtifactRepository local;
185 
186     /**
187      * {@inheritDoc}
188      */
189     protected Renderer getSiteRenderer()
190     {
191         return siteRenderer;
192     }
193 
194     /**
195      * {@inheritDoc}
196      */
197     protected String getOutputDirectory()
198     {
199         // PLUGIN-191: output directory of plugin.html, not *-mojo.xml
200         return project.getReporting().getOutputDirectory();
201     }
202 
203     /**
204      * {@inheritDoc}
205      */
206     protected MavenProject getProject()
207     {
208         return project;
209     }
210 
211     /**
212      * {@inheritDoc}
213      */
214     public boolean canGenerateReport()
215     {
216         return "maven-plugin".equals( project.getPackaging() );
217     }
218 
219     /**
220      * {@inheritDoc}
221      */
222     protected void executeReport( Locale locale )
223         throws MavenReportException
224     {
225         if ( !canGenerateReport() )
226         {
227             return;
228         }
229         if ( skip || skipReport )
230         {
231             getLog().info( "Maven Plugin Plugin Report generation skipped." );
232             return;
233         }
234 
235         PluginDescriptor pluginDescriptor = extractPluginDescriptor();
236 
237         // Generate the mojos' documentation
238         generateMojosDocumentation( pluginDescriptor, locale );
239 
240         // Write the overview
241         PluginOverviewRenderer r =
242             new PluginOverviewRenderer( project, requirements, getSink(), pluginDescriptor, locale );
243         r.render();
244     }
245 
246     private PluginDescriptor extractPluginDescriptor()
247         throws MavenReportException
248     {
249         // Copy from AbstractGeneratorMojo#execute()
250         String defaultGoalPrefix = PluginDescriptor.getGoalPrefixFromArtifactId( project.getArtifactId() );
251         if ( goalPrefix == null )
252         {
253             goalPrefix = defaultGoalPrefix;
254         }
255         else
256         {
257             getLog().warn( "\n\nGoal prefix is specified as: '" + goalPrefix + "'. Maven currently expects it to be '"
258                                + defaultGoalPrefix + "'.\n" );
259         }
260 
261         // TODO: could use this more, eg in the writing of the plugin descriptor!
262         PluginDescriptor pluginDescriptor = new PluginDescriptor();
263 
264         pluginDescriptor.setGroupId( project.getGroupId() );
265 
266         pluginDescriptor.setArtifactId( project.getArtifactId() );
267 
268         pluginDescriptor.setVersion( project.getVersion() );
269 
270         pluginDescriptor.setGoalPrefix( goalPrefix );
271 
272         try
273         {
274             @SuppressWarnings( "unchecked" )
275             List<ComponentDependency> deps = GeneratorUtils.toComponentDependencies( project.getRuntimeDependencies() );
276             pluginDescriptor.setDependencies( deps );
277 
278             PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
279             request.setEncoding( encoding );
280             request.setSkipErrorNoDescriptorsFound( true );
281             request.setDependencies( dependencies );
282             request.setLocal( this.local );
283             request.setRemoteRepos( this.remoteRepos );
284 
285             try
286             {
287                 mojoScanner.populatePluginDescriptor( request );
288             }
289             catch ( InvalidPluginDescriptorException e )
290             {
291                 // this is OK, it happens to lifecycle plugins. Allow generation to proceed.
292                 getLog().debug( "Plugin without mojos.", e );
293             }
294         }
295         catch ( ExtractionException e )
296         {
297             throw new MavenReportException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'",
298                                             e );
299         }
300         return pluginDescriptor;
301     }
302 
303     /**
304      * {@inheritDoc}
305      */
306     public String getDescription( Locale locale )
307     {
308         return getBundle( locale ).getString( "report.plugin.description" );
309     }
310 
311     /**
312      * {@inheritDoc}
313      */
314     public String getName( Locale locale )
315     {
316         return getBundle( locale ).getString( "report.plugin.name" );
317     }
318 
319     /**
320      * {@inheritDoc}
321      */
322     public String getOutputName()
323     {
324         return "plugin-info";
325     }
326 
327     /**
328      * Generate the mojos documentation, as xdoc files.
329      *
330      * @param pluginDescriptor not null
331      * @param locale           not null
332      * @throws MavenReportException if any
333      */
334     private void generateMojosDocumentation( PluginDescriptor pluginDescriptor, Locale locale )
335         throws MavenReportException
336     {
337         try
338         {
339             File outputDir = outputDirectory;
340             outputDir.mkdirs();
341 
342             PluginXdocGenerator generator = new PluginXdocGenerator( project, locale );
343             PluginToolsRequest pluginToolsRequest = new DefaultPluginToolsRequest( project, pluginDescriptor );
344             generator.execute( outputDir, pluginToolsRequest );
345         }
346         catch ( GeneratorException e )
347         {
348             throw new MavenReportException( "Error writing plugin documentation", e );
349         }
350 
351     }
352 
353     /**
354      * @param locale not null
355      * @return the bundle for this report
356      */
357     protected static ResourceBundle getBundle( Locale locale )
358     {
359         return ResourceBundle.getBundle( "plugin-report", locale, PluginReport.class.getClassLoader() );
360     }
361 
362     /**
363      * Generates an overview page with the list of goals
364      * and a link to the goal's page.
365      */
366     static class PluginOverviewRenderer
367         extends AbstractMavenReportRenderer
368     {
369         private final MavenProject project;
370 
371         private final Requirements requirements;
372 
373         private final PluginDescriptor pluginDescriptor;
374 
375         private final Locale locale;
376 
377         /**
378          * @param project          not null
379          * @param requirements     not null
380          * @param sink             not null
381          * @param pluginDescriptor not null
382          * @param locale           not null
383          */
384         public PluginOverviewRenderer( MavenProject project, Requirements requirements, Sink sink,
385                                        PluginDescriptor pluginDescriptor, Locale locale )
386         {
387             super( sink );
388 
389             this.project = project;
390 
391             this.requirements = ( requirements == null ? new Requirements() : requirements );
392 
393             this.pluginDescriptor = pluginDescriptor;
394 
395             this.locale = locale;
396         }
397 
398         /**
399          * {@inheritDoc}
400          */
401         public String getTitle()
402         {
403             return getBundle( locale ).getString( "report.plugin.title" );
404         }
405 
406         /**
407          * {@inheritDoc}
408          */
409         @SuppressWarnings( { "unchecked", "rawtypes" } )
410         public void renderBody()
411         {
412             startSection( getTitle() );
413 
414             if ( !( pluginDescriptor.getMojos() != null && pluginDescriptor.getMojos().size() > 0 ) )
415             {
416                 paragraph( getBundle( locale ).getString( "report.plugin.goals.nogoal" ) );
417                 endSection();
418                 return;
419             }
420 
421             paragraph( getBundle( locale ).getString( "report.plugin.goals.intro" ) );
422 
423             boolean hasMavenReport = false;
424             for ( Iterator<MojoDescriptor> i = pluginDescriptor.getMojos().iterator(); i.hasNext(); )
425             {
426                 MojoDescriptor mojo = i.next();
427 
428                 if ( GeneratorUtils.isMavenReport( mojo.getImplementation(), project ) )
429                 {
430                     hasMavenReport = true;
431                 }
432             }
433 
434             startTable();
435 
436             String goalColumnName = getBundle( locale ).getString( "report.plugin.goals.column.goal" );
437             String isMavenReport = getBundle( locale ).getString( "report.plugin.goals.column.isMavenReport" );
438             String descriptionColumnName = getBundle( locale ).getString( "report.plugin.goals.column.description" );
439             if ( hasMavenReport )
440             {
441                 tableHeader( new String[]{ goalColumnName, isMavenReport, descriptionColumnName } );
442             }
443             else
444             {
445                 tableHeader( new String[]{ goalColumnName, descriptionColumnName } );
446             }
447 
448             List<MojoDescriptor> mojos = new ArrayList<MojoDescriptor>();
449             mojos.addAll( pluginDescriptor.getMojos() );
450             PluginUtils.sortMojos( mojos );
451             for ( MojoDescriptor mojo : mojos )
452             {
453                 String goalName = mojo.getFullGoalName();
454 
455                 /*
456                  * Added ./ to define a relative path
457                  * @see AbstractMavenReportRenderer#getValidHref(java.lang.String)
458                  */
459                 String goalDocumentationLink = "./" + mojo.getGoal() + "-mojo.html";
460 
461                 String description;
462                 if ( StringUtils.isNotEmpty( mojo.getDeprecated() ) )
463                 {
464                     description =
465                         "<strong>" + getBundle( locale ).getString( "report.plugin.goal.deprecated" ) + "</strong> "
466                             + GeneratorUtils.makeHtmlValid( mojo.getDeprecated() );
467                 }
468                 else if ( StringUtils.isNotEmpty( mojo.getDescription() ) )
469                 {
470                     description = GeneratorUtils.makeHtmlValid( mojo.getDescription() );
471                 }
472                 else
473                 {
474                     description = getBundle( locale ).getString( "report.plugin.goal.nodescription" );
475                 }
476 
477                 sink.tableRow();
478                 tableCell( createLinkPatternedText( goalName, goalDocumentationLink ) );
479                 if ( hasMavenReport )
480                 {
481                     if ( GeneratorUtils.isMavenReport( mojo.getImplementation(), project ) )
482                     {
483                         sink.tableCell();
484                         sink.text( getBundle( locale ).getString( "report.plugin.isReport" ) );
485                         sink.tableCell_();
486                     }
487                     else
488                     {
489                         sink.tableCell();
490                         sink.text( getBundle( locale ).getString( "report.plugin.isNotReport" ) );
491                         sink.tableCell_();
492                     }
493                 }
494                 tableCell( description, true );
495                 sink.tableRow_();
496             }
497 
498             endTable();
499 
500             startSection( getBundle( locale ).getString( "report.plugin.systemrequirements" ) );
501 
502             paragraph( getBundle( locale ).getString( "report.plugin.systemrequirements.intro" ) );
503 
504             startTable();
505 
506             String maven = discoverMavenRequirement( project, requirements );
507             sink.tableRow();
508             tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.maven" ) );
509             tableCell( ( maven != null
510                 ? maven
511                 : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
512             sink.tableRow_();
513 
514             String jdk = discoverJdkRequirement( project, requirements );
515             sink.tableRow();
516             tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.jdk" ) );
517             tableCell(
518                 ( jdk != null ? jdk : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
519             sink.tableRow_();
520 
521             sink.tableRow();
522             tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.memory" ) );
523             tableCell( ( StringUtils.isNotEmpty( requirements.getMemory() )
524                 ? requirements.getMemory()
525                 : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
526             sink.tableRow_();
527 
528             sink.tableRow();
529             tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.diskspace" ) );
530             tableCell( ( StringUtils.isNotEmpty( requirements.getDiskSpace() )
531                 ? requirements.getDiskSpace()
532                 : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
533             sink.tableRow_();
534 
535             if ( requirements.getOthers() != null && requirements.getOthers().size() > 0 )
536             {
537                 for ( Iterator it = requirements.getOthers().keySet().iterator(); it.hasNext(); )
538                 {
539                     String key = it.next().toString();
540 
541                     sink.tableRow();
542                     tableCell( key );
543                     tableCell( ( StringUtils.isNotEmpty( requirements.getOthers().getProperty( key ) )
544                         ? requirements.getOthers().getProperty( key )
545                         : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
546                     sink.tableRow_();
547                 }
548             }
549             endTable();
550 
551             endSection();
552 
553             renderUsageSection( hasMavenReport );
554 
555             endSection();
556         }
557 
558         /**
559          * Render the section about the usage of the plugin.
560          *
561          * @param hasMavenReport If the plugin has a report or not
562          */
563         private void renderUsageSection( boolean hasMavenReport )
564         {
565             startSection( getBundle( locale ).getString( "report.plugin.usage" ) );
566 
567             // Configuration
568             sink.paragraph();
569             text( getBundle( locale ).getString( "report.plugin.usage.intro" ) );
570             sink.paragraph_();
571 
572             StringBuilder sb = new StringBuilder();
573             sb.append( "<project>" ).append( '\n' );
574             sb.append( "  ..." ).append( '\n' );
575             sb.append( "  <build>" ).append( '\n' );
576             sb.append(
577                 "    <!-- " + getBundle( locale ).getString( "report.plugin.usage.pluginManagement" ) + " -->" ).append(
578                 '\n' );
579             sb.append( "    <pluginManagement>" ).append( '\n' );
580             sb.append( "      <plugins>" ).append( '\n' );
581             sb.append( "        <plugin>" ).append( '\n' );
582             sb.append( "          <groupId>" ).append( pluginDescriptor.getGroupId() ).append( "</groupId>" ).append(
583                 '\n' );
584             sb.append( "          <artifactId>" ).append( pluginDescriptor.getArtifactId() ).append(
585                 "</artifactId>" ).append( '\n' );
586             sb.append( "          <version>" ).append( pluginDescriptor.getVersion() ).append( "</version>" ).append(
587                 '\n' );
588             sb.append( "        </plugin>" ).append( '\n' );
589             sb.append( "        ..." ).append( '\n' );
590             sb.append( "      </plugins>" ).append( '\n' );
591             sb.append( "    </pluginManagement>" ).append( '\n' );
592             sb.append( "    <!-- " + getBundle( locale ).getString( "report.plugin.usage.plugins" ) + " -->" ).append(
593                 '\n' );
594             sb.append( "    <plugins>" ).append( '\n' );
595             sb.append( "      <plugin>" ).append( '\n' );
596             sb.append( "        <groupId>" ).append( pluginDescriptor.getGroupId() ).append( "</groupId>" ).append(
597                 '\n' );
598             sb.append( "        <artifactId>" ).append( pluginDescriptor.getArtifactId() ).append(
599                 "</artifactId>" ).append( '\n' );
600             sb.append( "        <version>" ).append( pluginDescriptor.getVersion() ).append( "</version>" ).append(
601                 '\n' );
602             sb.append( "      </plugin>" ).append( '\n' );
603             sb.append( "      ..." ).append( '\n' );
604             sb.append( "    </plugins>" ).append( '\n' );
605             sb.append( "  </build>" ).append( '\n' );
606 
607             if ( hasMavenReport )
608             {
609                 sb.append( "  ..." ).append( '\n' );
610                 sb.append(
611                     "  <!-- " + getBundle( locale ).getString( "report.plugin.usage.reporting" ) + " -->" ).append(
612                     '\n' );
613                 sb.append( "  <reporting>" ).append( '\n' );
614                 sb.append( "    <plugins>" ).append( '\n' );
615                 sb.append( "      <plugin>" ).append( '\n' );
616                 sb.append( "        <groupId>" ).append( pluginDescriptor.getGroupId() ).append( "</groupId>" ).append(
617                     '\n' );
618                 sb.append( "        <artifactId>" ).append( pluginDescriptor.getArtifactId() ).append(
619                     "</artifactId>" ).append( '\n' );
620                 sb.append( "        <version>" ).append( pluginDescriptor.getVersion() ).append( "</version>" ).append(
621                     '\n' );
622                 sb.append( "      </plugin>" ).append( '\n' );
623                 sb.append( "      ..." ).append( '\n' );
624                 sb.append( "    </plugins>" ).append( '\n' );
625                 sb.append( "  </reporting>" ).append( '\n' );
626             }
627 
628             sb.append( "  ..." ).append( '\n' );
629             sb.append( "</project>" ).append( '\n' );
630 
631             verbatimText( sb.toString() );
632 
633             sink.paragraph();
634             linkPatternedText( getBundle( locale ).getString( "report.plugin.configuration.end" ) );
635             sink.paragraph_();
636 
637             endSection();
638         }
639 
640         /**
641          * Try to lookup on the Maven prerequisites property.
642          * If not specified, uses the value defined by the user.
643          *
644          * @param project      not null
645          * @param requirements not null
646          * @return the Maven version
647          */
648         private static String discoverMavenRequirement( MavenProject project, Requirements requirements )
649         {
650             String maven = requirements.getMaven();
651             if ( maven == null )
652             {
653                 maven = ( project.getPrerequisites() != null ? project.getPrerequisites().getMaven() : null );
654             }
655             if ( maven == null )
656             {
657                 maven = "2.0";
658             }
659 
660             return maven;
661         }
662 
663         /**
664          * <ol>
665          * <li>use configured jdk requirement</li>
666          * <li>use <code>target</code> configuration of <code>org.apache.maven.plugins:maven-compiler-plugin</code></li>
667          * <li>use <code>target</code> configuration of <code>org.apache.maven.plugins:maven-compiler-plugin</code> in
668          * <code>pluginManagement</code></li>
669          * <li>use <code>maven.compiler.target</code> property</li>
670          * </ol>
671          *
672          * @param project      not null
673          * @param requirements not null
674          * @return the JDK version
675          */
676         private static String discoverJdkRequirement( MavenProject project, Requirements requirements )
677         {
678             String jdk = requirements.getJdk();
679 
680             if ( jdk != null )
681             {
682                 return jdk;
683             }
684 
685             @SuppressWarnings( "unchecked" )
686             Plugin compiler = getCompilerPlugin( project.getBuild().getPluginsAsMap() );
687             if ( compiler == null )
688             {
689                 compiler = getCompilerPlugin( project.getPluginManagement().getPluginsAsMap() );
690             }
691 
692             jdk = getPluginParameter( compiler, "target" );
693             if ( jdk != null )
694             {
695                 return jdk;
696             }
697 
698             // default value
699             jdk = project.getProperties().getProperty( "maven.compiler.target" );
700             if ( jdk != null )
701             {
702                 return jdk;
703             }
704 
705             // return "1.5" by default?
706 
707             String version = ( compiler == null ) ? null : compiler.getVersion();
708 
709             if ( version != null )
710             {
711                 return "Default target for maven-compiler-plugin version " + version;
712             }
713 
714             return "Unknown";
715         }
716 
717         private static Plugin getCompilerPlugin( Map<String, Object> pluginsAsMap )
718         {
719             return (Plugin) pluginsAsMap.get( "org.apache.maven.plugins:maven-compiler-plugin" );
720         }
721 
722         private static String getPluginParameter( Plugin plugin, String parameter )
723         {
724             if ( plugin != null )
725             {
726                 Xpp3Dom pluginConf = (Xpp3Dom) plugin.getConfiguration();
727 
728                 if ( pluginConf != null )
729                 {
730                     Xpp3Dom target = pluginConf.getChild( parameter );
731 
732                     if ( target != null )
733                     {
734                         return target.getValue();
735                     }
736                 }
737             }
738 
739             return null;
740         }
741     }
742 }