blob: 85bb7ff9f7d15d91b515b66bd5730ccd1f1bf6f4 [file] [log] [blame]
/*
* 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.
*/
package org.apache.maven.tools.plugin.generator;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
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;
import org.apache.maven.project.MavenProject;
import org.apache.maven.tools.plugin.EnhancedParameterWrapper;
import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
import org.apache.maven.tools.plugin.PluginToolsRequest;
import org.apache.maven.tools.plugin.javadoc.JavadocLinkGenerator;
import org.codehaus.plexus.util.StringUtils;
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;
/**
* Generate <a href="https://maven.apache.org/doxia/references/xdoc-format.html">xdoc documentation</a> for each mojo.
*/
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
*/
private final Locale locale;
/**
* project
*/
private final MavenProject project;
/**
* The directory where the generated site is written.
* Used for resolving relative links to javadoc.
*/
private final File reportOutputDirectory;
private final boolean disableInternalJavadocLinkValidation;
/**
* Default constructor using <code>Locale.ENGLISH</code> as locale.
* Used only in test cases.
*/
public PluginXdocGenerator() {
this(null);
}
/**
* Constructor using <code>Locale.ENGLISH</code> as locale.
*
* @param project not null Maven project.
*/
public PluginXdocGenerator(MavenProject project) {
this(project, Locale.ENGLISH, new File("").getAbsoluteFile(), false);
}
/**
* @param project not null.
* @param locale not null.
*/
public PluginXdocGenerator(
MavenProject project,
Locale locale,
File reportOutputDirectory,
boolean disableInternalJavadocLinkValidation) {
this.project = project;
this.locale = locale;
this.reportOutputDirectory = reportOutputDirectory;
this.disableInternalJavadocLinkValidation = disableInternalJavadocLinkValidation;
}
/**
* {@inheritDoc}
*/
@Override
public void execute(File destinationDirectory, PluginToolsRequest request) throws GeneratorException {
try {
if (request.getPluginDescriptor().getMojos() != null) {
List<MojoDescriptor> mojos = request.getPluginDescriptor().getMojos();
for (MojoDescriptor descriptor : mojos) {
processMojoDescriptor(descriptor, destinationDirectory);
}
}
} catch (IOException e) {
throw new GeneratorException(e.getMessage(), e);
}
}
/**
* @param mojoDescriptor not null
* @param destinationDirectory not null
* @throws IOException if any
*/
protected void processMojoDescriptor(MojoDescriptor mojoDescriptor, File destinationDirectory) throws IOException {
File outputFile = new File(destinationDirectory, getMojoFilename(mojoDescriptor, "xml"));
try (Writer writer = new OutputStreamWriter(new CachingOutputStream(outputFile), UTF_8)) {
XMLWriter w = new PrettyPrintXMLWriter(new PrintWriter(writer), UTF_8.name(), null);
writeBody(mojoDescriptor, w);
writer.flush();
}
}
/**
* @param mojo not null
* @param ext not null
* @return the output file name
*/
private String getMojoFilename(MojoDescriptor mojo, String ext) {
return mojo.getGoal() + "-mojo." + ext;
}
/**
* @param mojoDescriptor not null
* @param w not null
*/
private void writeBody(MojoDescriptor mojoDescriptor, XMLWriter w) {
w.startElement("document");
w.addAttribute("xmlns", "http://maven.apache.org/XDOC/2.0");
w.addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
w.addAttribute(
"xsi:schemaLocation", "http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd");
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
w.startElement("properties");
w.startElement("title");
w.writeText(mojoDescriptor.getFullGoalName());
w.endElement(); // title
w.endElement(); // properties
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
w.startElement("body");
w.startElement("section");
w.addAttribute("name", mojoDescriptor.getFullGoalName());
writeReportNotice(mojoDescriptor, w);
w.startElement("p");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.fullname"));
w.endElement(); // p
w.startElement("p");
w.writeMarkup(mojoDescriptor.getPluginDescriptor().getGroupId() + ":"
+ mojoDescriptor.getPluginDescriptor().getArtifactId() + ":"
+ 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(getXhtmlWithValidatedLinks(mojoDescriptor.getDeprecated(), context));
w.endElement(); // div
}
w.startElement("p");
w.writeMarkup(getString("pluginxdoc.description"));
w.endElement(); // p
w.startElement("div");
if (StringUtils.isNotEmpty(mojoDescriptor.getDescription())) {
w.writeMarkup(getXhtmlWithValidatedLinks(mojoDescriptor.getDescription(), context));
} else {
w.writeText(getString("pluginxdoc.nodescription"));
}
w.endElement(); // div
writeGoalAttributes(mojoDescriptor, w);
writeGoalParameterTable(mojoDescriptor, w);
w.endElement(); // section
w.endElement(); // body
w.endElement(); // document
}
/**
* @param mojoDescriptor not null
* @param w not null
*/
private void writeReportNotice(MojoDescriptor mojoDescriptor, XMLWriter w) {
if (GeneratorUtils.isMavenReport(mojoDescriptor.getImplementation(), project)) {
w.startElement("p");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.notice.note"));
w.writeText(getString("pluginxdoc.mojodescriptor.notice.isMavenReport"));
w.endElement(); // p
}
}
/**
* @param mojoDescriptor not null
* @param w not null
*/
private void writeGoalAttributes(MojoDescriptor mojoDescriptor, XMLWriter w) {
w.startElement("p");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.attributes"));
w.endElement(); // p
boolean addedUl = false;
String value;
if (mojoDescriptor.isProjectRequired()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.projectRequired"));
w.endElement(); // li
}
if (mojoDescriptor.isRequiresReports()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.reportingMojo"));
w.endElement(); // li
}
if (mojoDescriptor.isAggregator()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.aggregator"));
w.endElement(); // li
}
if (mojoDescriptor.isDirectInvocationOnly()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.directInvocationOnly"));
w.endElement(); // li
}
value = mojoDescriptor.isDependencyResolutionRequired();
if (value != null && !value.isEmpty()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(format("pluginxdoc.mojodescriptor.dependencyResolutionRequired", value));
w.endElement(); // li
}
if (mojoDescriptor instanceof ExtendedMojoDescriptor) {
ExtendedMojoDescriptor extendedMojoDescriptor = (ExtendedMojoDescriptor) mojoDescriptor;
value = extendedMojoDescriptor.getDependencyCollectionRequired();
if (value != null && !value.isEmpty()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(format("pluginxdoc.mojodescriptor.dependencyCollectionRequired", value));
w.endElement(); // li
}
}
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(getString(
mojoDescriptor.isThreadSafe()
? "pluginxdoc.mojodescriptor.threadSafe"
: "pluginxdoc.mojodescriptor.notThreadSafe"));
w.endElement(); // li
value = mojoDescriptor.getSince();
if (value != null && !value.isEmpty()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(format("pluginxdoc.mojodescriptor.since", value));
w.endElement(); // li
}
value = mojoDescriptor.getPhase();
if (value != null && !value.isEmpty()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(format("pluginxdoc.mojodescriptor.phase", value));
w.endElement(); // li
}
value = mojoDescriptor.getExecutePhase();
if (value != null && !value.isEmpty()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(format("pluginxdoc.mojodescriptor.executePhase", value));
w.endElement(); // li
}
value = mojoDescriptor.getExecuteGoal();
if (value != null && !value.isEmpty()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(format("pluginxdoc.mojodescriptor.executeGoal", value));
w.endElement(); // li
}
value = mojoDescriptor.getExecuteLifecycle();
if (value != null && !value.isEmpty()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(format("pluginxdoc.mojodescriptor.executeLifecycle", value));
w.endElement(); // li
}
if (mojoDescriptor.isOnlineRequired()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.onlineRequired"));
w.endElement(); // li
}
if (!mojoDescriptor.isInheritedByDefault()) {
addedUl = addUl(w, addedUl);
w.startElement("li");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.inheritedByDefault"));
w.endElement(); // li
}
if (addedUl) {
w.endElement(); // ul
}
}
/**
* @param mojoDescriptor not null
* @param w not null
*/
private void writeGoalParameterTable(MojoDescriptor mojoDescriptor, XMLWriter w) {
List<Parameter> parameterList = mojoDescriptor.getParameters();
// remove components and read-only parameters
List<Parameter> list = filterParameters(parameterList);
if (!list.isEmpty()) {
writeParameterSummary(list, w, mojoDescriptor.getGoal());
writeParameterDetails(list, w, mojoDescriptor.getGoal());
} else {
w.startElement("subsection");
w.addAttribute("name", getString("pluginxdoc.mojodescriptor.parameters"));
w.startElement("p");
w.writeMarkup(getString("pluginxdoc.mojodescriptor.noParameter"));
w.endElement(); // p
w.endElement();
}
}
/**
* Filter parameters to only retain those which must be documented, i.e. neither components nor readonly.
*
* @param parameterList not null
* @return the parameters list without components.
*/
private List<Parameter> filterParameters(List<Parameter> parameterList) {
List<Parameter> filtered = new ArrayList<>();
if (parameterList != null) {
for (Parameter parameter : parameterList) {
if (parameter.isEditable()) {
String expression = parameter.getExpression();
if (expression == null || !expression.startsWith("${component.")) {
filtered.add(parameter);
}
}
}
}
return filtered;
}
/**
* @param parameterList not null
* @param w not null
*/
private void writeParameterDetails(List<Parameter> parameterList, XMLWriter w, String goal) {
w.startElement("subsection");
w.addAttribute("name", getString("pluginxdoc.mojodescriptor.parameter.details"));
for (Iterator<Parameter> parameters = parameterList.iterator(); parameters.hasNext(); ) {
Parameter parameter = parameters.next();
w.startElement("h4");
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");
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(getXhtmlWithValidatedLinks(parameter.getDescription(), context));
} else {
w.writeMarkup(getString("pluginxdoc.nodescription"));
}
w.endElement(); // div
boolean addedUl = false;
addedUl = addUl(w, addedUl, parameter.getType());
String typeValue = getLinkedType(parameter, false);
writeDetail(getString("pluginxdoc.mojodescriptor.parameter.type"), typeValue, w);
if (StringUtils.isNotEmpty(parameter.getSince())) {
addedUl = addUl(w, addedUl);
writeDetail(getString("pluginxdoc.mojodescriptor.parameter.since"), parameter.getSince(), w);
}
if (parameter.isRequired()) {
addedUl = addUl(w, addedUl);
writeDetail(getString("pluginxdoc.mojodescriptor.parameter.required"), getString("pluginxdoc.yes"), w);
} else {
addedUl = addUl(w, addedUl);
writeDetail(getString("pluginxdoc.mojodescriptor.parameter.required"), getString("pluginxdoc.no"), w);
}
String expression = parameter.getExpression();
addedUl = addUl(w, addedUl, expression);
String property = getPropertyFromExpression(expression);
if (property == null) {
writeDetail(getString("pluginxdoc.mojodescriptor.parameter.expression"), expression, w);
} else {
writeDetail(getString("pluginxdoc.mojodescriptor.parameter.property"), property, w);
}
addedUl = addUl(w, addedUl, parameter.getDefaultValue());
writeDetail(
getString("pluginxdoc.mojodescriptor.parameter.default"),
escapeXml(parameter.getDefaultValue()),
w);
addedUl = addUl(w, addedUl, parameter.getAlias());
writeDetail(getString("pluginxdoc.mojodescriptor.parameter.alias"), escapeXml(parameter.getAlias()), w);
if (addedUl) {
w.endElement(); // ul
}
if (parameters.hasNext()) {
w.writeMarkup("<hr/>");
}
}
w.endElement();
}
static String getShortType(String type) {
// split into type arguments and main type
int startTypeArguments = type.indexOf('<');
if (startTypeArguments == -1) {
return getShortTypeOfSimpleType(type);
} else {
StringBuilder shortType = new StringBuilder();
shortType.append(getShortTypeOfSimpleType(type.substring(0, startTypeArguments)));
shortType
.append("<")
.append(getShortTypeOfTypeArgument(type.substring(startTypeArguments + 1, type.lastIndexOf(">"))))
.append(">");
return shortType.toString();
}
}
private static String getShortTypeOfTypeArgument(String type) {
String[] typeArguments = type.split(",\\s*");
StringBuilder shortType = new StringBuilder();
for (int i = 0; i < typeArguments.length; i++) {
String typeArgument = typeArguments[i];
if (typeArgument.contains("<")) {
// nested type arguments lead to ellipsis
return "...";
} else {
shortType.append(getShortTypeOfSimpleType(typeArgument));
if (i < typeArguments.length - 1) {
shortType.append(",");
}
}
}
return shortType.toString();
}
private static String getShortTypeOfSimpleType(String type) {
int index = type.lastIndexOf('.');
return type.substring(index + 1);
}
private String getLinkedType(Parameter parameter, boolean isShortType) {
final String typeValue;
if (isShortType) {
typeValue = getShortType(parameter.getType());
} else {
typeValue = parameter.getType();
}
if (parameter instanceof EnhancedParameterWrapper) {
EnhancedParameterWrapper enhancedParameter = (EnhancedParameterWrapper) parameter;
if (enhancedParameter.getTypeJavadocUrl() != null) {
URI javadocUrl = enhancedParameter.getTypeJavadocUrl();
// optionally check if link is valid
if (javadocUrl.isAbsolute()
|| disableInternalJavadocLinkValidation
|| JavadocLinkGenerator.isLinkValid(javadocUrl, reportOutputDirectory.toPath())) {
return format(
"pluginxdoc.mojodescriptor.parameter.type_link",
new Object[] {escapeXml(typeValue), enhancedParameter.getTypeJavadocUrl()});
}
}
}
return escapeXml(typeValue);
}
private boolean addUl(XMLWriter w, boolean addedUl, String content) {
if (content != null && !content.isEmpty()) {
return addUl(w, addedUl);
}
return addedUl;
}
private boolean addUl(XMLWriter w, boolean addedUl) {
if (!addedUl) {
w.startElement("ul");
addedUl = true;
}
return addedUl;
}
private String getPropertyFromExpression(String expression) {
if ((expression != null && !expression.isEmpty())
&& expression.startsWith("${")
&& expression.endsWith("}")
&& !expression.substring(2).contains("${")) {
// expression="${xxx}" -> property="xxx"
return expression.substring(2, expression.length() - 1);
}
// no property can be extracted
return null;
}
/**
* @param param not null
* @param value could be null
* @param w not null
*/
private void writeDetail(String param, String value, XMLWriter w) {
if (value != null && !value.isEmpty()) {
w.startElement("li");
w.writeMarkup(format("pluginxdoc.detail", new String[] {param, value}));
w.endElement(); // li
}
}
/**
* @param parameterList not null
* @param w not null
*/
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, goal);
}
List<Parameter> optionalParams = getParametersByRequired(false, parameterList);
if (!optionalParams.isEmpty()) {
writeParameterList(getString("pluginxdoc.mojodescriptor.optionalParameters"), optionalParams, w, goal);
}
}
/**
* @param title not null
* @param parameterList not null
* @param w not null
*/
private void writeParameterList(String title, List<Parameter> parameterList, XMLWriter w, String goal) {
w.startElement("subsection");
w.addAttribute("name", title);
w.startElement("table");
w.addAttribute("border", "0");
w.addAttribute("class", "bodyTable");
w.startElement("tr");
w.startElement("th");
w.writeText(getString("pluginxdoc.mojodescriptor.parameter.name"));
w.endElement(); // th
w.startElement("th");
w.writeText(getString("pluginxdoc.mojodescriptor.parameter.type"));
w.endElement(); // th
w.startElement("th");
w.writeText(getString("pluginxdoc.mojodescriptor.parameter.since"));
w.endElement(); // th
w.startElement("th");
w.writeText(getString("pluginxdoc.mojodescriptor.parameter.description"));
w.endElement(); // th
w.endElement(); // tr
for (Parameter parameter : parameterList) {
w.startElement("tr");
// name
w.startElement("td");
w.writeMarkup(format("pluginxdoc.mojodescriptor.parameter.name_link", parameter.getName()));
w.endElement(); // td
// type
w.startElement("td");
w.writeMarkup("<code>" + getLinkedType(parameter, true) + "</code>");
w.endElement(); // td
// since
w.startElement("td");
if (StringUtils.isNotEmpty(parameter.getSince())) {
w.writeMarkup("<code>" + parameter.getSince() + "</code>");
} else {
w.writeMarkup("<code>-</code>");
}
w.endElement(); // td
// description
w.startElement("td");
String description;
String context = "Parameter " + parameter.getName() + " in goal " + goal;
if (StringUtils.isNotEmpty(parameter.getDeprecated())) {
String deprecated = getXhtmlWithValidatedLinks(parameter.getDescription(), context);
description = format("pluginxdoc.mojodescriptor.parameter.deprecated", deprecated);
} else if (StringUtils.isNotEmpty(parameter.getDescription())) {
description = getXhtmlWithValidatedLinks(parameter.getDescription(), context);
} else {
description = getString("pluginxdoc.nodescription");
}
w.writeMarkup(description + "<br/>");
if (StringUtils.isNotEmpty(parameter.getDefaultValue())) {
w.writeMarkup(format(
"pluginxdoc.mojodescriptor.parameter.defaultValue", escapeXml(parameter.getDefaultValue())));
w.writeMarkup("<br/>");
}
String property = getPropertyFromExpression(parameter.getExpression());
if (property != null) {
w.writeMarkup(format("pluginxdoc.mojodescriptor.parameter.property.description", property));
w.writeMarkup("<br/>");
}
if (StringUtils.isNotEmpty(parameter.getAlias())) {
w.writeMarkup(format(
"pluginxdoc.mojodescriptor.parameter.alias.description", escapeXml(parameter.getAlias())));
}
w.endElement(); // td
w.endElement(); // tr
}
w.endElement(); // table
w.endElement(); // section
}
/**
* @param required <code>true</code> for required parameters, <code>false</code> otherwise.
* @param parameterList not null
* @return list of parameters depending the value of <code>required</code>
*/
private List<Parameter> getParametersByRequired(boolean required, List<Parameter> parameterList) {
List<Parameter> list = new ArrayList<>();
for (Parameter parameter : parameterList) {
if (parameter.isRequired() == required) {
list.add(parameter);
}
}
return list;
}
/**
* Gets the resource bundle for the <code>locale</code> instance variable.
*
* @return The resource bundle for the <code>locale</code> instance variable.
*/
private ResourceBundle getBundle() {
return ResourceBundle.getBundle("pluginxdoc", locale, getClass().getClassLoader());
}
/**
* @param key not null
* @return Localized, text identified by <code>key</code>.
* @see #getBundle()
*/
private String getString(String key) {
return getBundle().getString(key);
}
/**
* Convenience method.
*
* @param key not null
* @param arg1 not null
* @return Localized, formatted text identified by <code>key</code>.
* @see #format(String, Object[])
*/
private String format(String key, Object arg1) {
return format(key, new Object[] {arg1});
}
/**
* Looks up the value for <code>key</code> in the <code>ResourceBundle</code>,
* then formats that value for the specified <code>Locale</code> using <code>args</code>.
*
* @param key not null
* @param args not null
* @return Localized, formatted text identified by <code>key</code>.
*/
private String format(String key, Object[] args) {
String pattern = getString(key);
// we don't need quoting so spare us the confusion in the resource bundle to double them up in some keys
pattern = StringUtils.replace(pattern, "'", "''");
MessageFormat messageFormat = new MessageFormat("");
messageFormat.setLocale(locale);
messageFormat.applyPattern(pattern);
return messageFormat.format(args);
}
/**
* @param text the string to escape
* @return A string escaped with XML entities
*/
private String escapeXml(String text) {
if (text != null) {
text = text.replace("&", "&amp;");
text = text.replace("<", "&lt;");
text = text.replace(">", "&gt;");
text = text.replace("\"", "&quot;");
text = text.replace("\'", "&apos;");
}
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();
}
}