blob: 1a2473424017b7730101e0dfcde979c036f55e73 [file] [log] [blame]
package org.apache.maven.plugin.docck;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.docck.reports.DocumentationReporter;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.project.MavenProject;
import org.apache.maven.tools.plugin.extractor.ExtractionException;
import org.apache.maven.tools.plugin.scanner.MojoScanner;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
/**
* Checks a plugin's documentation for the standard minimums.
*
* @author jdcasey
*/
@Mojo( name = "check", aggregator = true, defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true )
public class CheckPluginDocumentationMojo
extends AbstractCheckDocumentationMojo
{
/**
* Plexus component that searches for Mojos.
*/
@Component
protected MojoScanner mojoScanner;
// TODO: really a description of length 1 isn't all that helpful...
private static final int MIN_DESCRIPTION_LENGTH = 1;
protected void checkPackagingSpecificDocumentation( MavenProject project, DocumentationReporter reporter )
{
PluginDescriptor descriptor = new PluginDescriptor();
try
{
mojoScanner.populatePluginDescriptor( project, descriptor );
}
catch ( InvalidPluginDescriptorException e )
{
reporter.error( "Failed to parse mojo descriptors.\nError: " + e.getMessage() );
descriptor = null;
}
catch ( ExtractionException e )
{
reporter.error( "Failed to parse mojo descriptors.\nError: " + e.getMessage() );
descriptor = null;
}
if ( descriptor != null )
{
@SuppressWarnings( "unchecked" )
List<MojoDescriptor> mojos = descriptor.getMojos();
// ensure that all mojo classes are documented
if ( mojos != null && !mojos.isEmpty() )
{
for ( MojoDescriptor mojo : mojos )
{
String mojoDescription = mojo.getDescription();
if ( mojoDescription == null || mojoDescription.trim().length() < MIN_DESCRIPTION_LENGTH )
{
reporter.error( "Mojo: \'" + mojo.getGoal() + "\' is missing a description." );
}
@SuppressWarnings( "unchecked" )
List<Parameter> params = mojo.getParameters();
// ensure that all parameters are documented
if ( params != null && !params.isEmpty() )
{
for ( Parameter param : params )
{
if ( param.getRequirement() == null && param.isEditable() )
{
String paramDescription = param.getDescription();
if ( paramDescription == null
|| paramDescription.trim().length() < MIN_DESCRIPTION_LENGTH )
{
reporter.error( "Parameter: \'" + param.getName() + "\' in mojo: \'"
+ mojo.getGoal() + "\' is missing a description." );
}
}
}
}
}
}
}
checkConfiguredReportPlugins( project, reporter );
checkProjectSite( project, reporter );
}
protected boolean approveProjectPackaging( String packaging )
{
return "maven-plugin".equals( packaging );
}
private void checkProjectSite( MavenProject project, DocumentationReporter reporter )
{
File projectSiteDirectory = new File( project.getBasedir(), siteDirectory );
// check for site.xml
File siteXml = new File( projectSiteDirectory, "site.xml" );
if ( !siteXml.exists() )
{
reporter.error( "site.xml is missing." );
}
else
{
Reader streamReader = null;
try
{
streamReader = ReaderFactory.newXmlReader( siteXml );
String siteHtml = IOUtil.toString( streamReader );
streamReader.close();
streamReader = null;
if ( !siteHtml.contains( "href=\"index.html\"" ) )
{
reporter.error( "site.xml is missing the link to: index.html \"Introduction\"." );
}
if ( !siteHtml.contains( "href=\"usage.html\"" ) )
{
reporter.error( "site.xml is missing the link to: usage.html \"Usage\"." );
}
if ( !siteHtml.contains( "href=\"plugin-info.html\"" ) )
{
reporter.error( "site.xml is missing the link to: plugin-info.html \"Goals\"." );
}
if ( !siteHtml.contains( "href=\"faq.html\"" ) )
{
reporter.error( "site.xml is missing the link to: faq.html \"FAQ\"." );
}
}
catch ( IOException e )
{
reporter.error( "Unable to read site.xml file: \'" + siteXml.getAbsolutePath() + "\'.\nError: "
+ e.getMessage() );
}
finally
{
IOUtil.close( streamReader );
}
}
// check for index.(apt|html|xml)[.vm]
if ( !findFiles( projectSiteDirectory, "index" ) )
{
reporter.error( "There is no \'index\' file in your site directory (in apt|html|xml[.vm] format)." );
}
// check for usage.(apt|html|xml)[.vm]
if ( !findFiles( projectSiteDirectory, "usage" ) )
{
reporter.error( "There is no \'usage\' file in your site directory (in apt|html|xml[.vm] format)." );
}
// check for **/examples/**.(apt|html|xml)[.vm] or **/example*.(apt|html|xml)[.vm]
if ( !findFiles( projectSiteDirectory, "**/examples/*" ) && !findFiles( projectSiteDirectory, "**/example*" ) )
{
reporter.error( "There are no example files in your site directory (in apt|html|xml[.vm] format)."
+ " They should either be called \'example*.(apt|html|xml)[.vm]\'"
+ " or they should be located in the \'examples\' directory." );
}
if ( !findFiles( projectSiteDirectory, "faq" ) )
{
reporter.error( "There is no \'faq\' file in your site directory (in apt|fml|html|xml[.vm] format)." );
}
}
/**
* Checks the project configured plugins if the required report plugins are present.
*
* @param project MavenProject to check
* @param reporter listener
* @todo maybe this should be checked default for all project?
*/
private void checkConfiguredReportPlugins( MavenProject project, DocumentationReporter reporter )
{
List<String> expectedPlugins = getRequiredPlugins();
@SuppressWarnings( "unchecked" )
List<ReportPlugin> reportPlugins = project.getReportPlugins();
if ( reportPlugins != null && reportPlugins.size() > 0 )
{
for ( ReportPlugin plugin : reportPlugins )
{
expectedPlugins.remove( plugin.getArtifactId() );
}
}
else
{
reporter.error( "pom.xml has no report plugins configured." );
}
for ( String expectedPlugin : expectedPlugins )
{
reporter.error( "pom.xml is missing the report plugin: " + expectedPlugin + "." );
}
}
/**
* Returns a List of Strings of required report plugins.
*
* @return List of report plugin artifactIds
*/
private List<String> getRequiredPlugins()
{
List<String> list = new ArrayList<String>();
list.add( "maven-javadoc-plugin" );
list.add( "maven-jxr-plugin" );
return list;
}
}