Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MPLUGIN-433] Allow to disable link validation #162

Merged
merged 3 commits into from Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -218,6 +218,19 @@ public class PluginReport
readonly = true )
private File enhancedPluginXmlFile;

/**
* In case the internal javadoc site has not been generated when running this report goal
* (e.g. when using an aggregator javadoc report) link validation needs to be disabled by setting
* this value to {@code true}.
* This might have the drawback that some links being generated in the report might be broken
* in case not all parameter types and javadoc link references are resolvable through the sites being given to
* {@link DescriptorGeneratorMojo}.
*
* @since 3.7.0
*/
@Parameter
private boolean disableInternalJavadocLinkValidation;
slawekjaranowski marked this conversation as resolved.
Show resolved Hide resolved

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -324,7 +337,8 @@ private void generateMojosDocumentation( PluginDescriptor pluginDescriptor, Loca
File outputDir = outputDirectory;
outputDir.mkdirs();

PluginXdocGenerator generator = new PluginXdocGenerator( getProject(), locale, getReportOutputDirectory() );
PluginXdocGenerator generator = new PluginXdocGenerator( getProject(), locale, getReportOutputDirectory(),
disableInternalJavadocLinkValidation );
PluginToolsRequest pluginToolsRequest = new DefaultPluginToolsRequest( getProject(), pluginDescriptor );
generator.execute( outputDir, pluginToolsRequest );
}
Expand Down
Expand Up @@ -130,6 +130,19 @@ public class PluginReport
readonly = true )
private File enhancedPluginXmlFile;

/**
* In case the internal javadoc site has not been generated when running this report goal
* (e.g. when using an aggregator javadoc report) link validation needs to be disabled by setting
* this value to {@code true}.
* This might have the drawback that some links being generated in the report might be broken
* in case not all parameter types and javadoc link references are resolvable through the sites being given to
* goal {@code plugin:descriptor}.
*
* @since 3.7.0
*/
@Parameter
private boolean disableInternalJavadocLinkValidation;

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -232,7 +245,8 @@ private void generateMojosDocumentation( PluginDescriptor pluginDescriptor, Loca
File outputDir = outputDirectory;
outputDir.mkdirs();

PluginXdocGenerator generator = new PluginXdocGenerator( getProject(), locale, getReportOutputDirectory() );
PluginXdocGenerator generator = new PluginXdocGenerator( getProject(), locale, getReportOutputDirectory(),
disableInternalJavadocLinkValidation );
PluginToolsRequest pluginToolsRequest = new DefaultPluginToolsRequest( getProject(), pluginDescriptor );
generator.execute( outputDir, pluginToolsRequest );
}
Expand Down
Expand Up @@ -253,7 +253,13 @@ public static boolean isLinkValid( URI url, Path baseDirectory )
}
else
{
return Files.exists( baseDirectory.resolve( url.getPath() ) );
Path file = baseDirectory.resolve( url.getPath() );
boolean exists = Files.exists( file );
if ( !exists )
{
LOG.debug( "Could not find file given through '{}' in resolved path '{}'", url, file );
}
return exists;
}
}
}
5 changes: 5 additions & 0 deletions maven-plugin-tools-generators/pom.xml
Expand Up @@ -113,6 +113,11 @@
<artifactId>maven-plugin-testing-harness</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Expand Up @@ -25,12 +25,15 @@
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
Expand All @@ -43,6 +46,8 @@
import org.codehaus.plexus.util.io.CachingOutputStream;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
import org.codehaus.plexus.util.xml.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.nio.charset.StandardCharsets.UTF_8;

Expand All @@ -52,6 +57,14 @@
public class PluginXdocGenerator
implements Generator
{
/**
* Regular expression matching an XHTML link
* group 1 = link target, group 2 = link label
*/
private static final Pattern HTML_LINK_PATTERN = Pattern.compile( "<a href=\\\"([^\\\"]*)\\\">(.*?)</a>" );

private static final Logger LOG = LoggerFactory.getLogger( PluginXdocGenerator.class );

/**
* locale
*/
Expand All @@ -68,6 +81,8 @@ public class PluginXdocGenerator
*/
private final File reportOutputDirectory;

private final boolean disableInternalJavadocLinkValidation;

/**
* Default constructor using <code>Locale.ENGLISH</code> as locale.
* Used only in test cases.
Expand All @@ -84,14 +99,15 @@ public PluginXdocGenerator()
*/
public PluginXdocGenerator( MavenProject project )
{
this( project, Locale.ENGLISH, new File( "" ).getAbsoluteFile() );
this( project, Locale.ENGLISH, new File( "" ).getAbsoluteFile(), false );
}

/**
* @param project not null.
* @param locale not null wanted locale.
*/
public PluginXdocGenerator( MavenProject project, Locale locale, File reportOutputDirectory )
public PluginXdocGenerator( MavenProject project, Locale locale, File reportOutputDirectory,
boolean disableInternalJavadocLinkValidation )
{
this.project = project;
if ( locale == null )
Expand All @@ -103,6 +119,7 @@ public PluginXdocGenerator( MavenProject project, Locale locale, File reportOutp
this.locale = locale;
}
this.reportOutputDirectory = reportOutputDirectory;
this.disableInternalJavadocLinkValidation = disableInternalJavadocLinkValidation;
}


Expand Down Expand Up @@ -204,13 +221,14 @@ private void writeBody( MojoDescriptor mojoDescriptor, XMLWriter w )
+ mojoDescriptor.getPluginDescriptor().getVersion() + ":" + mojoDescriptor.getGoal() );
w.endElement(); //p

String context = "goal " + mojoDescriptor.getGoal();
if ( StringUtils.isNotEmpty( mojoDescriptor.getDeprecated() ) )
{
w.startElement( "p" );
w.writeMarkup( getString( "pluginxdoc.mojodescriptor.deprecated" ) );
w.endElement(); // p
w.startElement( "div" );
w.writeMarkup( mojoDescriptor.getDeprecated() );
w.writeMarkup( getXhtmlWithValidatedLinks( mojoDescriptor.getDeprecated(), context ) );
w.endElement(); // div
}

Expand All @@ -220,7 +238,7 @@ private void writeBody( MojoDescriptor mojoDescriptor, XMLWriter w )
w.startElement( "div" );
if ( StringUtils.isNotEmpty( mojoDescriptor.getDescription() ) )
{
w.writeMarkup( mojoDescriptor.getDescription() );
w.writeMarkup( getXhtmlWithValidatedLinks( mojoDescriptor.getDescription(), context ) );
}
else
{
Expand Down Expand Up @@ -408,8 +426,8 @@ private void writeGoalParameterTable( MojoDescriptor mojoDescriptor, XMLWriter w

if ( !list.isEmpty() )
{
writeParameterSummary( list, w );
writeParameterDetails( list, w );
writeParameterSummary( list, w, mojoDescriptor.getGoal() );
writeParameterDetails( list, w, mojoDescriptor.getGoal() );
}
else
{
Expand Down Expand Up @@ -457,7 +475,7 @@ private List<Parameter> filterParameters( List<Parameter> parameterList )
* @param parameterList not null
* @param w not null
*/
private void writeParameterDetails( List<Parameter> parameterList, XMLWriter w )
private void writeParameterDetails( List<Parameter> parameterList, XMLWriter w, String goal )
{
w.startElement( "subsection" );
w.addAttribute( "name", getString( "pluginxdoc.mojodescriptor.parameter.details" ) );
Expand All @@ -470,17 +488,20 @@ private void writeParameterDetails( List<Parameter> parameterList, XMLWriter w )
w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.name_internal", parameter.getName() ) );
w.endElement();

String context = "Parameter " + parameter.getName() + " in goal " + goal;
if ( StringUtils.isNotEmpty( parameter.getDeprecated() ) )
{
w.startElement( "div" );
w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.deprecated", parameter.getDeprecated() ) );
String deprecated = getXhtmlWithValidatedLinks( parameter.getDeprecated(), context );
w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.deprecated", deprecated ) );
w.endElement(); // div
}

w.startElement( "div" );
if ( StringUtils.isNotEmpty( parameter.getDescription() ) )
{
w.writeMarkup( parameter.getDescription() );

w.writeMarkup( getXhtmlWithValidatedLinks( parameter.getDescription(), context ) );
}
else
{
Expand Down Expand Up @@ -613,10 +634,11 @@ private String getLinkedType( Parameter parameter, boolean isShortType )
EnhancedParameterWrapper enhancedParameter = (EnhancedParameterWrapper) parameter;
if ( enhancedParameter.getTypeJavadocUrl() != null )
{
// check if link is valid
URI javadocUrl = enhancedParameter.getTypeJavadocUrl();
// optionally check if link is valid
if ( javadocUrl.isAbsolute()
|| JavadocLinkGenerator.isLinkValid( javadocUrl, reportOutputDirectory.toPath() ) )
|| !disableInternalJavadocLinkValidation
&& JavadocLinkGenerator.isLinkValid( javadocUrl, reportOutputDirectory.toPath() ) )
{
return format( "pluginxdoc.mojodescriptor.parameter.type_link",
new Object[] { escapeXml( typeValue ), enhancedParameter.getTypeJavadocUrl() } );
Expand Down Expand Up @@ -676,20 +698,20 @@ private void writeDetail( String param, String value, XMLWriter w )
* @param parameterList not null
* @param w not null
*/
private void writeParameterSummary( List<Parameter> parameterList, XMLWriter w )
private void writeParameterSummary( List<Parameter> parameterList, XMLWriter w, String goal )
{
List<Parameter> requiredParams = getParametersByRequired( true, parameterList );
if ( !requiredParams.isEmpty() )
{
writeParameterList( getString( "pluginxdoc.mojodescriptor.requiredParameters" ),
requiredParams, w );
requiredParams, w, goal );
}

List<Parameter> optionalParams = getParametersByRequired( false, parameterList );
if ( !optionalParams.isEmpty() )
{
writeParameterList( getString( "pluginxdoc.mojodescriptor.optionalParameters" ),
optionalParams, w );
optionalParams, w, goal );
}
}

Expand All @@ -698,7 +720,7 @@ private void writeParameterSummary( List<Parameter> parameterList, XMLWriter w )
* @param parameterList not null
* @param w not null
*/
private void writeParameterList( String title, List<Parameter> parameterList, XMLWriter w )
private void writeParameterList( String title, List<Parameter> parameterList, XMLWriter w, String goal )
{
w.startElement( "subsection" );
w.addAttribute( "name", title );
Expand Down Expand Up @@ -750,13 +772,15 @@ private void writeParameterList( String title, List<Parameter> parameterList, XM
// description
w.startElement( "td" );
String description;
String context = "Parameter " + parameter.getName() + " in goal " + goal;
if ( StringUtils.isNotEmpty( parameter.getDeprecated() ) )
{
description = format( "pluginxdoc.mojodescriptor.parameter.deprecated", parameter.getDeprecated() );
String deprecated = getXhtmlWithValidatedLinks( parameter.getDescription(), context );
description = format( "pluginxdoc.mojodescriptor.parameter.deprecated", deprecated );
}
else if ( StringUtils.isNotEmpty( parameter.getDescription() ) )
{
description = parameter.getDescription();
description = getXhtmlWithValidatedLinks( parameter.getDescription(), context );
}
else
{
Expand Down Expand Up @@ -883,4 +907,38 @@ private String escapeXml( String text )
return text;
}

String getXhtmlWithValidatedLinks( String xhtmlText, String context )
{
if ( disableInternalJavadocLinkValidation )
{
return xhtmlText;
}
StringBuffer sanitizedXhtmlText = new StringBuffer();
// find all links which are not absolute
Matcher matcher = HTML_LINK_PATTERN.matcher( xhtmlText );
while ( matcher.find() )
{
URI link;
try
{
link = new URI( matcher.group( 1 ) );
if ( !link.isAbsolute() && !JavadocLinkGenerator.isLinkValid( link, reportOutputDirectory.toPath() ) )
{
matcher.appendReplacement( sanitizedXhtmlText, matcher.group( 2 ) );
LOG.debug( "Removed invalid link {} in {}", link, context );
}
else
{
matcher.appendReplacement( sanitizedXhtmlText, matcher.group( 0 ) );
}
}
catch ( URISyntaxException e )
{
LOG.warn( "Invalid URI {} found in {}. Cannot validate, leave untouched", matcher.group( 1 ), context );
matcher.appendReplacement( sanitizedXhtmlText, matcher.group( 0 ) );
}
}
matcher.appendTail( sanitizedXhtmlText );
return sanitizedXhtmlText.toString();
}
}
Expand Up @@ -21,6 +21,7 @@

import java.io.File;
import java.io.InputStream;
import java.util.Locale;

import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.Xpp3Dom;
Expand Down Expand Up @@ -63,4 +64,22 @@ void testGetShortType()
assertEquals("Map<String,Integer>", PluginXdocGenerator.getShortType( "java.util.Map<java.lang.String,java.lang.Integer>" ) );
assertEquals("List<...>", PluginXdocGenerator.getShortType( "java.util.List<java.util.List<java.lang.String>>" ) );
}

@Test
void testGetXhtmlWithValidatedLinks()
{
File baseDir = new File( this.getClass().getResource( "" ).getFile() );
PluginXdocGenerator xdocGenerator = new PluginXdocGenerator( null, Locale.ROOT, baseDir, false );
PluginXdocGenerator xdocGeneratorWithDisabledLinkValidator = new PluginXdocGenerator( null, Locale.ROOT, baseDir, true );
String externalLink = "test<a href=\"http://example.com/test\">External Link</a>..and a second<a href=\"http://localhost/example\">link</a>end";
assertEquals( externalLink, xdocGenerator.getXhtmlWithValidatedLinks( externalLink, "test" ) );
assertEquals( externalLink, xdocGeneratorWithDisabledLinkValidator.getXhtmlWithValidatedLinks( externalLink, "test" ) );
String validInternalLink = "test<a href=\"PluginXdocGeneratorTest.class\">Internal Link</a>..and a second<a href=\"http://localhost/example\">link</a>end";
assertEquals( validInternalLink, xdocGenerator.getXhtmlWithValidatedLinks( validInternalLink, "test" ) );
assertEquals( validInternalLink, xdocGeneratorWithDisabledLinkValidator.getXhtmlWithValidatedLinks( validInternalLink, "test" ) );
String invalidInternalLink = "test<a href=\"PluginXdocGeneratorTestinvalid.class\">Internal Link</a>..and a second<a href=\"http://localhost/example\">link</a>end";
String sanitizedInvalidInternalLink = "testInternal Link..and a second<a href=\"http://localhost/example\">link</a>end";
assertEquals( sanitizedInvalidInternalLink, xdocGenerator.getXhtmlWithValidatedLinks( invalidInternalLink, "test" ) );
assertEquals( invalidInternalLink, xdocGeneratorWithDisabledLinkValidator.getXhtmlWithValidatedLinks( invalidInternalLink, "test" ) );
}
}