diff --git a/maven-plugin-report-plugin/pom.xml b/maven-plugin-report-plugin/pom.xml index 04cdf80e5..21ad8498a 100644 --- a/maven-plugin-report-plugin/pom.xml +++ b/maven-plugin-report-plugin/pom.xml @@ -77,10 +77,6 @@ org.apache.maven.plugin-tools maven-plugin-tools-api - - org.apache.maven.plugin-tools - maven-plugin-tools-generators - @@ -95,6 +91,12 @@ maven-reporting-impl + + org.apache.commons + commons-lang3 + 3.8.1 + + org.codehaus.plexus diff --git a/maven-plugin-report-plugin/src/it/mplugin-191/verify.groovy b/maven-plugin-report-plugin/src/it/mplugin-191/verify.groovy index 5a33abdd5..24506b919 100644 --- a/maven-plugin-report-plugin/src/it/mplugin-191/verify.groovy +++ b/maven-plugin-report-plugin/src/it/mplugin-191/verify.groovy @@ -18,7 +18,7 @@ File pluginInfo = new File( basedir, "target/site/plugin-info.html" ); assert pluginInfo.isFile() -File touchMojo = new File( basedir, "target/generated-site/xdoc/touch-mojo.xml" ); +File touchMojo = new File( basedir, "target/site/touch-mojo.html" ); assert touchMojo.isFile() return true; diff --git a/maven-plugin-report-plugin/src/it/mplugin-319_report-since/verify.groovy b/maven-plugin-report-plugin/src/it/mplugin-319_report-since/verify.groovy index 21c533288..877d8f83b 100644 --- a/maven-plugin-report-plugin/src/it/mplugin-319_report-since/verify.groovy +++ b/maven-plugin-report-plugin/src/it/mplugin-319_report-since/verify.groovy @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -assert new File( basedir, 'target/generated-site' ).exists() +assert new File( basedir, 'target/site/noop-mojo.html' ).exists() -content = new File( basedir, 'target/generated-site/xdoc/noop-mojo.xml' ).text +content = new File( basedir, 'target/site/noop-mojo.html' ).text -assert content.contains( '
  • Since version: 1.0
  • ' ) +assert content.contains( '
  • Since version: 1.0.
  • ' ) assert content.contains( '-' ) assert content.contains( '1.1' ) assert content.contains( '
  • Since: 1.1
  • ' ) diff --git a/maven-plugin-report-plugin/src/it/mplugin-394_report-encoding/verify.groovy b/maven-plugin-report-plugin/src/it/mplugin-394_report-encoding/verify.groovy index f7699228c..e10b63081 100644 --- a/maven-plugin-report-plugin/src/it/mplugin-394_report-encoding/verify.groovy +++ b/maven-plugin-report-plugin/src/it/mplugin-394_report-encoding/verify.groovy @@ -17,7 +17,7 @@ * under the License. */ -generated = new File( basedir, "target/generated-site/xdoc/test-mojo.xml").getText("UTF-8") +generated = new File( basedir, "target/site/test-mojo.html").getText("UTF-8") assert generated.contains("Mojo-Description with some non-ASCII characters: €àáâãäåæòóôõöø") assert generated.contains("Parameter-Description with some non-ASCII characters: ÈÉÊË€") diff --git a/maven-plugin-report-plugin/src/it/plugin-report-with-javadoc-links/verify.groovy b/maven-plugin-report-plugin/src/it/plugin-report-with-javadoc-links/verify.groovy index 5eb43a120..158ea3e8d 100644 --- a/maven-plugin-report-plugin/src/it/plugin-report-with-javadoc-links/verify.groovy +++ b/maven-plugin-report-plugin/src/it/plugin-report-with-javadoc-links/verify.groovy @@ -21,13 +21,13 @@ def mojoDoc = new File( basedir, 'target/site/test-mojo.html' ) assert mojoDoc.isFile() -assert mojoDoc.text.contains('See also: java.util.Collections') // mojo description see javadoc tag +assert mojoDoc.text.contains('See also: java.util.Collections') // mojo description see javadoc tag assert mojoDoc.text.contains('beans parameter leveraging SimpleBean.') // parameter description -assert mojoDoc.text.contains('Collection<SimpleBean>') // type link in parameter overview -assert mojoDoc.text.contains('
  • Type: java.util.Collection<org.SimpleBean>
  • ') // type link in parameter details +assert mojoDoc.text.contains('Collection<SimpleBean>') // type link in parameter overview +assert mojoDoc.text.contains('
  • Type: java.util.Collection<org.SimpleBean>
  • ') // type link in parameter details -assert mojoDoc.text.contains('
    invalid javadoc reference org.apache.maven.artifact.Artifact.
    ') // second parameter description with link being removed (as no javadoc site associated) +assert mojoDoc.text.contains('invalid javadoc reference org.apache.maven.artifact.Artifact') // second parameter description with link being removed (as no javadoc site associated) // the third parameter contains an invalid link (as the internal link validation has been switched off) -assert mojoDoc.text.contains(' org.internal.PrivateBean') +assert mojoDoc.text.contains(' org.internal.PrivateBean') diff --git a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/AbstractPluginReportRenderer.java b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/AbstractPluginReportRenderer.java new file mode 100644 index 000000000..d35634ec2 --- /dev/null +++ b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/AbstractPluginReportRenderer.java @@ -0,0 +1,74 @@ +/* + * 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.plugin.plugin.report; + +import java.util.Locale; + +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.AbstractMavenReportRenderer; +import org.codehaus.plexus.i18n.I18N; + +/** Base class for all reports generated by the plugin report plugin. */ +public abstract class AbstractPluginReportRenderer extends AbstractMavenReportRenderer { + + private static final String RESOURCE_BASENAME = "plugin-report"; + + private final I18N i18n; + + protected final Locale locale; + + protected final MavenProject project; + + protected AbstractPluginReportRenderer(Sink sink, Locale locale, I18N i18n, MavenProject project) { + super(sink); + this.i18n = i18n; + this.locale = locale; + this.project = project; + } + + @Override + public String getTitle() { + return getI18nString("title"); + } + + /** + * Returns + * @param key The key . + * @return The translated string. + */ + protected String getI18nString(String key) { + return getI18nString(getI18nSection(), key); + } + + /** + * @param section The section. + * @param key The key to translate. + * @return the translated key. + */ + protected String getI18nString(String section, String key) { + return i18n.getString(RESOURCE_BASENAME, locale, "report." + section + '.' + key); + } + + /** + * + * @return the key prefix to be used with every key. Is prepended by {@code report.}. + */ + protected abstract String getI18nSection(); +} diff --git a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/GoalRenderer.java b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/GoalRenderer.java new file mode 100644 index 000000000..eac6c0c7d --- /dev/null +++ b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/GoalRenderer.java @@ -0,0 +1,526 @@ +/* + * 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.plugin.plugin.report; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.MessageFormat; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet.Semantics; +import org.apache.maven.doxia.util.HtmlTools; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.plugin.logging.Log; +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.javadoc.JavadocLinkGenerator; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.i18n.I18N; + +public class GoalRenderer extends AbstractPluginReportRenderer { + + /** Regular expression matching an XHTML link with group 1 = link target, group 2 = link label. */ + private static final Pattern HTML_LINK_PATTERN = Pattern.compile("(.*?)"); + + /** The directory where the generated site is written. Used for resolving relative links to javadoc. */ + private final File reportOutputDirectory; + + private final MojoDescriptor descriptor; + private final boolean disableInternalJavadocLinkValidation; + + private final Log log; + + public GoalRenderer( + Sink sink, + I18N i18n, + Locale locale, + MavenProject project, + MojoDescriptor descriptor, + File reportOutputDirectory, + boolean disableInternalJavadocLinkValidation, + Log log) { + super(sink, locale, i18n, project); + this.reportOutputDirectory = reportOutputDirectory; + this.descriptor = descriptor; + this.disableInternalJavadocLinkValidation = disableInternalJavadocLinkValidation; + this.log = log; + } + + @Override + public String getTitle() { + return descriptor.getFullGoalName(); + } + + @Override + protected void renderBody() { + startSection(descriptor.getFullGoalName()); + renderReportNotice(); + renderDescription("fullname", descriptor.getPluginDescriptor().getId() + ":" + descriptor.getGoal(), false); + + String context = "goal " + descriptor.getGoal(); + if (StringUtils.isNotEmpty(descriptor.getDeprecated())) { + renderDescription("deprecated", getXhtmlWithValidatedLinks(descriptor.getDeprecated(), context), true); + } + if (StringUtils.isNotEmpty(descriptor.getDescription())) { + renderDescription("description", getXhtmlWithValidatedLinks(descriptor.getDescription(), context), true); + } else { + renderDescription("description", getI18nString("nodescription"), false); + } + renderAttributes(); + + List parameterList = filterParameters( + descriptor.getParameters() != null ? descriptor.getParameters() : Collections.emptyList()); + if (parameterList.isEmpty()) { + startSection(getI18nString("parameters")); + sink.paragraph(); + sink.text(getI18nString("noParameter")); + sink.paragraph_(); + endSection(); + } else { + renderParameterOverviewTable( + getI18nString("requiredParameters"), + parameterList.stream().filter(Parameter::isRequired).iterator()); + renderParameterOverviewTable( + getI18nString("optionalParameters"), + parameterList.stream().filter(p -> !p.isRequired()).iterator()); + renderParameterDetails(parameterList.iterator()); + } + endSection(); + } + + /** Filter parameters to only retain those which must be documented, i.e. neither components nor read-only ones. + * + * @param parameterList not null + * @return the parameters list without components. */ + private static List filterParameters(Collection parameterList) { + return parameterList.stream() + .filter(p -> p.isEditable() + && (p.getExpression() == null || !p.getExpression().startsWith("${component."))) + .collect(Collectors.toList()); + } + + private void renderReportNotice() { + if (PluginUtils.isMavenReport(descriptor.getImplementation(), project)) { + renderDescription("notice.prefix", getI18nString("notice.isMavenReport"), false); + } + } + + /** + * A description consists of a term/prefix and the actual description text + */ + private void renderDescription(String prefixKey, String description, boolean isHtmlMarkup) { + // TODO: convert to dt and dd elements + renderDescriptionPrefix(prefixKey); + sink.paragraph(); + if (isHtmlMarkup) { + sink.rawText(description); + } else { + sink.text(description); + } + sink.paragraph_(); // p + } + + private void renderDescriptionPrefix(String prefixKey) { + sink.paragraph(); + sink.inline(Semantics.STRONG); + sink.text(getI18nString(prefixKey)); + sink.inline_(); + sink.text(":"); + sink.paragraph_(); + } + + @SuppressWarnings("deprecation") + private void renderAttributes() { + renderDescriptionPrefix("attributes"); + sink.list(); + + renderAttribute(descriptor.isProjectRequired(), "projectRequired"); + renderAttribute(descriptor.isRequiresReports(), "reportingMojo"); + renderAttribute(descriptor.isAggregator(), "aggregator"); + renderAttribute(descriptor.isDirectInvocationOnly(), "directInvocationOnly"); + renderAttribute(descriptor.isDependencyResolutionRequired(), "dependencyResolutionRequired"); + + if (descriptor instanceof ExtendedMojoDescriptor) { + ExtendedMojoDescriptor extendedDescriptor = (ExtendedMojoDescriptor) descriptor; + renderAttribute(extendedDescriptor.getDependencyCollectionRequired(), "dependencyCollectionRequired"); + } + + renderAttribute(descriptor.isThreadSafe(), "threadSafe"); + renderAttribute(!descriptor.isThreadSafe(), "notThreadSafe"); + renderAttribute(descriptor.getSince(), "since"); + renderAttribute(descriptor.getPhase(), "phase"); + renderAttribute(descriptor.getExecutePhase(), "executePhase"); + renderAttribute(descriptor.getExecuteGoal(), "executeGoal"); + renderAttribute(descriptor.getExecuteLifecycle(), "executeLifecycle"); + renderAttribute(descriptor.isOnlineRequired(), "onlineRequired"); + renderAttribute(!descriptor.isInheritedByDefault(), "notInheritedByDefault"); + + sink.list_(); + } + + private void renderAttribute(boolean condition, String attributeKey) { + renderAttribute(condition, attributeKey, Optional.empty()); + } + + private void renderAttribute(String conditionAndCodeArgument, String attributeKey) { + renderAttribute( + StringUtils.isNotEmpty(conditionAndCodeArgument), + attributeKey, + Optional.ofNullable(conditionAndCodeArgument)); + } + + private void renderAttribute(boolean condition, String attributeKey, Optional codeArgument) { + if (condition) { + sink.listItem(); + linkPatternedText(getI18nString(attributeKey)); + if (codeArgument.isPresent()) { + text(": "); + sink.inline(Semantics.CODE); + sink.text(codeArgument.get()); + sink.inline_(); + } + text("."); + sink.listItem_(); + } + } + + private void renderParameterOverviewTable(String title, Iterator parameters) { + // don't emit empty tables + if (!parameters.hasNext()) { + return; + } + startSection(title); + startTable(); + tableHeader(new String[] { + getI18nString("parameter.name.header"), + getI18nString("parameter.type.header"), + getI18nString("parameter.since.header"), + getI18nString("parameter.description.header") + }); + while (parameters.hasNext()) { + renderParameterOverviewTableRow(parameters.next()); + } + endTable(); + endSection(); + } + + private void renderTableCellWithCode(String text) { + renderTableCellWithCode(text, Optional.empty()); + } + + private void renderTableCellWithCode(String text, Optional link) { + sink.tableCell(); + if (link.isPresent()) { + sink.link(link.get(), null); + } + sink.inline(Semantics.CODE); + sink.text(text); + sink.inline_(); + if (link.isPresent()) { + sink.link_(); + } + sink.tableCell_(); + } + + private void renderParameterOverviewTableRow(Parameter parameter) { + sink.tableRow(); + // name + // link to appropriate section + renderTableCellWithCode( + format("parameter.name", parameter.getName()), + // no need for additional URI encoding as it returns only URI safe characters + Optional.of("#" + HtmlTools.encodeId(parameter.getName()))); + + // type + Map.Entry> type = getLinkedType(parameter, true); + renderTableCellWithCode(type.getKey(), type.getValue()); + + // since + String since = StringUtils.defaultIfEmpty(parameter.getSince(), "-"); + renderTableCellWithCode(since); + + // description + sink.tableCell(); + String description; + String context = "Parameter " + parameter.getName() + " in goal " + descriptor.getGoal(); + if (StringUtils.isNotEmpty(parameter.getDeprecated())) { + String deprecated = getXhtmlWithValidatedLinks(parameter.getDescription(), context); + description = format("parameter.deprecated", deprecated); + } else if (StringUtils.isNotEmpty(parameter.getDescription())) { + description = getXhtmlWithValidatedLinks(parameter.getDescription(), context); + } else { + description = getI18nString("nodescription"); + } + sink.rawText(description); + renderTableCellDetail("parameter.defaultValue", parameter.getDefaultValue()); + renderTableCellDetail("parameter.property", getPropertyFromExpression(parameter.getExpression())); + renderTableCellDetail("parameter.alias", parameter.getAlias()); + sink.tableCell_(); + + sink.tableRow_(); + } + + private void renderParameterDetails(Iterator parameters) { + + startSection(getI18nString("parameter.details")); + + while (parameters.hasNext()) { + Parameter parameter = parameters.next(); + // deprecated anchor for backwards-compatibility with XDoc (upper and lower case) + // TODO: remove once migrated to Doxia 2.x + sink.anchor(parameter.getName()); + + startSection(format("parameter.name", parameter.getName())); + sink.anchor_(); + String context = "Parameter " + parameter.getName() + " in goal " + descriptor.getGoal(); + if (StringUtils.isNotEmpty(parameter.getDeprecated())) { + sink.division(); + String deprecated = getXhtmlWithValidatedLinks(parameter.getDeprecated(), context); + sink.rawText(format("parameter.deprecated", deprecated)); + sink.division_(); + } + + sink.division(); + if (StringUtils.isNotEmpty(parameter.getDescription())) { + sink.rawText(getXhtmlWithValidatedLinks(parameter.getDescription(), context)); + } else { + sink.text(getI18nString("nodescription")); + } + sink.division_(); + + sink.list(); + Map.Entry> typeAndLink = getLinkedType(parameter, false); + renderDetail(getI18nString("parameter.type"), typeAndLink.getKey(), typeAndLink.getValue()); + + if (StringUtils.isNotEmpty(parameter.getSince())) { + renderDetail(getI18nString("parameter.since"), parameter.getSince()); + } + + if (parameter.isRequired()) { + renderDetail(getI18nString("parameter.required"), getI18nString("yes")); + } else { + renderDetail(getI18nString("parameter.required"), getI18nString("no")); + } + + String expression = parameter.getExpression(); + String property = getPropertyFromExpression(expression); + if (property == null) { + renderDetail(getI18nString("parameter.expression"), expression); + } else { + renderDetail(getI18nString("parameter.property"), property); + } + + renderDetail(getI18nString("parameter.defaultValue"), parameter.getDefaultValue()); + + renderDetail(getI18nString("parameter.alias"), parameter.getAlias()); + + sink.list_(); // ul + + if (parameters.hasNext()) { + sink.horizontalRule(); + } + endSection(); + } + endSection(); + } + + private void renderTableCellDetail(String nameKey, String value) { + if (StringUtils.isNotEmpty(value)) { + sink.lineBreak(); + sink.inline(Semantics.STRONG); + sink.text(getI18nString(nameKey)); + sink.inline_(); + sink.text(": "); + sink.inline(Semantics.CODE); + sink.text(value); + sink.inline_(); + } + } + + private void renderDetail(String param, String value) { + renderDetail(param, value, Optional.empty()); + } + + private void renderDetail(String param, String value, Optional valueLink) { + if (value != null && !value.isEmpty()) { + sink.listItem(); + sink.inline(Semantics.STRONG); + sink.text(param); + sink.inline_(); + sink.text(": "); + if (valueLink.isPresent()) { + sink.link(valueLink.get()); + } + sink.inline(Semantics.CODE); + sink.text(value); + sink.inline_(); + if (valueLink.isPresent()) { + sink.link_(); + } + sink.listItem_(); + } + } + + private static 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; + } + + 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 Map.Entry> getLinkedType(Parameter parameter, boolean isShortType) { + final String typeValue; + if (isShortType) { + typeValue = getShortType(parameter.getType()); + } else { + typeValue = parameter.getType(); + } + URI uri = null; + 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())) { + uri = enhancedParameter.getTypeJavadocUrl(); + } + } + } + // rely on the encoded URI + return new SimpleEntry<>(typeValue, Optional.ofNullable(uri).map(URI::toASCIIString)); + } + + 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(String.format("Removed invalid link %s in %s", link, context)); + } else { + matcher.appendReplacement(sanitizedXhtmlText, matcher.group(0)); + } + } catch (URISyntaxException e) { + log.warn(String.format( + "Invalid URI %s found in %s. Cannot validate, leave untouched", matcher.group(1), context)); + matcher.appendReplacement(sanitizedXhtmlText, matcher.group(0)); + } + } + matcher.appendTail(sanitizedXhtmlText); + return sanitizedXhtmlText.toString(); + } + + /** Convenience method. + * + * @param key not null + * @param arg1 not null + * @return Localized, formatted text identified by key. + * @see #format(String, Object[]) */ + private String format(String key, Object arg1) { + return format(key, new Object[] {arg1}); + } + + /** Looks up the value for key in the ResourceBundle, then formats that value for the specified + * Locale using args. + * + * @param key not null + * @param args not null + * @return Localized, formatted text identified by key. */ + private String format(String key, Object[] args) { + String pattern = getI18nString(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(pattern, locale); + return messageFormat.format(args); + } + + @Override + protected String getI18nSection() { + return "plugin.goal"; + } +} diff --git a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginOverviewRenderer.java b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginOverviewRenderer.java new file mode 100644 index 000000000..5189357e4 --- /dev/null +++ b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginOverviewRenderer.java @@ -0,0 +1,394 @@ +/* + * 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.plugin.plugin.report; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.doxia.markup.Markup; +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.Prerequisites; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.project.MavenProject; +import org.apache.maven.tools.plugin.ExtendedPluginDescriptor; +import org.apache.maven.tools.plugin.util.PluginUtils; +import org.codehaus.plexus.i18n.I18N; +import org.codehaus.plexus.util.xml.Xpp3Dom; + +/** + * Generates an overview page with the list of goals + * and a link to the goal's page. + */ +class PluginOverviewRenderer extends AbstractPluginReportRenderer { + + private final List requirementsHistories; + + private final PluginDescriptor pluginDescriptor; + + private final boolean hasExtensionsToLoad; + + /** + * @param sink not null + * @param i18n not null + * @param locale not null + * @param project not null + * @param requirementsHistories not null + * @param pluginDescriptor not null + */ + PluginOverviewRenderer( + Sink sink, + I18N i18n, + Locale locale, + MavenProject project, + List requirementsHistories, + PluginDescriptor pluginDescriptor, + boolean hasExtensionsToLoad) { + super(sink, locale, i18n, project); + + this.requirementsHistories = requirementsHistories; + + this.pluginDescriptor = pluginDescriptor; + + this.hasExtensionsToLoad = hasExtensionsToLoad; + } + + /** + * {@inheritDoc} + */ + @Override + protected void renderBody() { + startSection(getTitle()); + + if (!(pluginDescriptor.getMojos() != null && pluginDescriptor.getMojos().size() > 0)) { + paragraph(getI18nString("goals.nogoal")); + endSection(); + return; + } + + paragraph(getI18nString("goals.intro")); + + boolean hasMavenReport = false; + for (MojoDescriptor mojo : pluginDescriptor.getMojos()) { + if (PluginUtils.isMavenReport(mojo.getImplementation(), project)) { + hasMavenReport = true; + } + } + + startTable(); + + String goalColumnName = getI18nString("goals.column.goal"); + String isMavenReport = getI18nString("goals.column.isMavenReport"); + String descriptionColumnName = getI18nString("goals.column.description"); + if (hasMavenReport) { + tableHeader(new String[] {goalColumnName, isMavenReport, descriptionColumnName}); + } else { + tableHeader(new String[] {goalColumnName, descriptionColumnName}); + } + + List mojos = new ArrayList<>(); + mojos.addAll(pluginDescriptor.getMojos()); + PluginUtils.sortMojos(mojos); + for (MojoDescriptor mojo : mojos) { + sink.tableRow(); + + String goalName = mojo.getFullGoalName(); + /* + * Added ./ to define a relative path + * @see AbstractMavenReportRenderer#getValidHref(java.lang.String) + */ + String goalDocumentationLink = "./" + mojo.getGoal() + "-mojo.html"; + sink.tableCell(); + link(goalDocumentationLink, goalName); + sink.tableCell_(); + + if (hasMavenReport) { + if (PluginUtils.isMavenReport(mojo.getImplementation(), project)) { + tableCell(getI18nString("isReport")); + } else { + tableCell(getI18nString("isNotReport")); + } + } + + String description; + if (StringUtils.isNotEmpty(mojo.getDeprecated())) { + description = "" + getI18nString("goal.deprecated") + " " + mojo.getDeprecated(); + } else if (StringUtils.isNotEmpty(mojo.getDescription())) { + description = mojo.getDescription(); + } else { + description = getI18nString("goal.nodescription"); + } + tableCell(description, true); + sink.tableRow_(); + } + + endTable(); + + startSection(getI18nString("systemrequirements")); + + paragraph(getI18nString("systemrequirements.intro")); + + startTable(); + + String maven = discoverMavenRequirement(project, pluginDescriptor); + sink.tableRow(); + tableCell(getI18nString("systemrequirements.maven")); + tableCell((maven != null ? maven : getI18nString("systemrequirements.nominimum"))); + sink.tableRow_(); + + String jdk = discoverJdkRequirement(project, pluginDescriptor); + sink.tableRow(); + tableCell(getI18nString("systemrequirements.jdk")); + tableCell((jdk != null ? jdk : getI18nString("systemrequirements.nominimum"))); + sink.tableRow_(); + + endTable(); + + endSection(); + + renderRequirementsHistories(); + + renderUsageSection(hasMavenReport); + + endSection(); + } + + private void renderRequirementsHistories() { + if (requirementsHistories.isEmpty()) { + return; + } + + startSection(getI18nString("systemrequirements.history")); + paragraph(getI18nString("systemrequirements.history.intro")); + + startTable(); + tableHeader(new String[] { + getI18nString("systemrequirements.history.version"), + getI18nString("systemrequirements.history.maven"), + getI18nString("systemrequirements.history.jdk") + }); + + requirementsHistories.forEach(requirementsHistory -> { + sink.tableRow(); + tableCell(requirementsHistory.getVersion()); + tableCell(requirementsHistory.getMaven()); + tableCell(requirementsHistory.getJdk()); + sink.tableRow_(); + }); + endTable(); + + endSection(); + } + + /** + * Render the section about the usage of the plugin. + * + * @param hasMavenReport If the plugin has a report or not + */ + private void renderUsageSection(boolean hasMavenReport) { + startSection(getI18nString("usage")); + + // Configuration + paragraph(getI18nString("usage.intro")); + + StringBuilder sb = new StringBuilder(); + sb.append("").append(Markup.EOL); + sb.append(" ...").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ") + .append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ") + .append(pluginDescriptor.getGroupId()) + .append("") + .append(Markup.EOL); + sb.append(" ") + .append(pluginDescriptor.getArtifactId()) + .append("") + .append(Markup.EOL); + sb.append(" ") + .append(pluginDescriptor.getVersion()) + .append("") + .append(Markup.EOL); + if (hasExtensionsToLoad) { + sb.append(" true").append(Markup.EOL); + } + sb.append(" ").append(Markup.EOL); + sb.append(" ...").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ") + .append(pluginDescriptor.getGroupId()) + .append("") + .append(Markup.EOL); + sb.append(" ") + .append(pluginDescriptor.getArtifactId()) + .append("") + .append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ...").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + + if (hasMavenReport) { + sb.append(" ...").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ") + .append(pluginDescriptor.getGroupId()) + .append("") + .append(Markup.EOL); + sb.append(" ") + .append(pluginDescriptor.getArtifactId()) + .append("") + .append(Markup.EOL); + sb.append(" ") + .append(pluginDescriptor.getVersion()) + .append("") + .append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ...").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + sb.append(" ").append(Markup.EOL); + } + + sb.append(" ...").append(Markup.EOL); + sb.append(""); + + verbatimText(sb.toString()); + + sink.paragraph(); + linkPatternedText(getI18nString("configuration.end")); + sink.paragraph_(); + + endSection(); + } + + /** + * Tries to determine the Maven requirement from either the plugin descriptor or (if not set) from the + * Maven prerequisites element in the POM. + * + * @param project not null + * @param pluginDescriptor the plugin descriptor (not null) + * @return the Maven version or null if not specified + */ + private static String discoverMavenRequirement(MavenProject project, PluginDescriptor pluginDescriptor) { + if (StringUtils.isNotBlank(pluginDescriptor.getRequiredMavenVersion())) { + return pluginDescriptor.getRequiredMavenVersion(); + } + return Optional.ofNullable(project.getPrerequisites()) + .map(Prerequisites::getMaven) + .orElse(null); + } + + /** + * Tries to determine the JDK requirement from the following sources (until one is found) + *
      + *
    1. use JDK requirement from plugin descriptor
    2. + *
    3. use {@code release} configuration of {@code org.apache.maven.plugins:maven-compiler-plugin}
    4. + *
    5. use {@code maven.compiler.release<} property
    6. + *
    7. use {@code target} configuration of {@code org.apache.maven.plugins:maven-compiler-plugin}
    8. + *
    9. use {@code maven.compiler.target} property
    10. + *
    + * + * @param project not null + * @param pluginDescriptor the plugin descriptor (not null) + * @return the JDK version + */ + private static String discoverJdkRequirement(MavenProject project, PluginDescriptor pluginDescriptor) { + String jdk = null; + if (pluginDescriptor instanceof ExtendedPluginDescriptor) { + ExtendedPluginDescriptor extPluginDescriptor = (ExtendedPluginDescriptor) pluginDescriptor; + jdk = extPluginDescriptor.getRequiredJavaVersion(); + } + if (jdk != null) { + return jdk; + } + Plugin compiler = getCompilerPlugin(project.getBuild().getPluginsAsMap()); + if (compiler == null) { + compiler = getCompilerPlugin(project.getPluginManagement().getPluginsAsMap()); + } + + jdk = getPluginParameter(compiler, "release"); + if (jdk != null) { + return jdk; + } + + jdk = project.getProperties().getProperty("maven.compiler.release"); + if (jdk != null) { + return jdk; + } + + jdk = getPluginParameter(compiler, "target"); + if (jdk != null) { + return jdk; + } + + // default value + jdk = project.getProperties().getProperty("maven.compiler.target"); + if (jdk != null) { + return jdk; + } + + String version = (compiler == null) ? null : compiler.getVersion(); + + if (version != null) { + return "Default target for maven-compiler-plugin version " + version; + } + + return null; + } + + private static Plugin getCompilerPlugin(Map pluginsAsMap) { + return pluginsAsMap.get("org.apache.maven.plugins:maven-compiler-plugin"); + } + + private static String getPluginParameter(Plugin plugin, String parameter) { + if (plugin != null) { + Xpp3Dom pluginConf = (Xpp3Dom) plugin.getConfiguration(); + + if (pluginConf != null) { + Xpp3Dom target = pluginConf.getChild(parameter); + + if (target != null) { + return target.getValue(); + } + } + } + + return null; + } + + @Override + protected String getI18nSection() { + return "plugin"; + } +} diff --git a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java index c9a174061..1e63aa29f 100644 --- a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java +++ b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java @@ -25,14 +25,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import org.apache.maven.doxia.markup.Markup; import org.apache.maven.doxia.sink.Sink; -import org.apache.maven.doxia.tools.SiteTool; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.Prerequisites; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder; @@ -42,23 +36,12 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.plugin.descriptor.EnhancedPluginDescriptorBuilder; -import org.apache.maven.project.MavenProject; import org.apache.maven.reporting.AbstractMavenReport; -import org.apache.maven.reporting.AbstractMavenReportRenderer; import org.apache.maven.reporting.MavenReportException; import org.apache.maven.rtinfo.RuntimeInformation; -import org.apache.maven.tools.plugin.DefaultPluginToolsRequest; -import org.apache.maven.tools.plugin.ExtendedPluginDescriptor; -import org.apache.maven.tools.plugin.PluginToolsRequest; -import org.apache.maven.tools.plugin.generator.GeneratorException; -import org.apache.maven.tools.plugin.generator.GeneratorUtils; -import org.apache.maven.tools.plugin.generator.PluginXdocGenerator; -import org.apache.maven.tools.plugin.util.PluginUtils; import org.codehaus.plexus.configuration.PlexusConfigurationException; import org.codehaus.plexus.i18n.I18N; -import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.XmlStreamReader; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Generates the Plugin's documentation report: plugin-info.html plugin overview page, @@ -72,13 +55,6 @@ @Mojo(name = "report", threadSafe = true) @Execute(phase = LifecyclePhase.PROCESS_CLASSES) public class PluginReport extends AbstractMavenReport { - /** - * Report output directory for mojos' documentation. - * - * @since 3.7.0 - */ - @Parameter(defaultValue = "${project.build.directory}/generated-site") - private File generatedSiteDirectory; /** * Set this to "true" to skip generating the report. @@ -147,15 +123,6 @@ public class PluginReport extends AbstractMavenReport { @Parameter(property = "maven.plugin.report.disableInternalJavadocLinkValidation") private boolean disableInternalJavadocLinkValidation; - /** - * {@inheritDoc} - */ - @Override - protected String getOutputDirectory() { - // PLUGIN-191: output directory of plugin.html, not *-mojo.xml - return project.getReporting().getOutputDirectory(); - } - /** * {@inheritDoc} */ @@ -229,403 +196,36 @@ public String getOutputName() { } /** - * Generate the mojos documentation, as xdoc files. + * Generate the mojos' documentation with the {@link #getSinkFactory()} * * @param pluginDescriptor not null * @param locale not null * @throws MavenReportException if any + * @throws IOException */ private void generateMojosDocumentation(PluginDescriptor pluginDescriptor, Locale locale) throws MavenReportException { - try { - File outputDir; - if (!locale.equals(SiteTool.DEFAULT_LOCALE)) { - outputDir = new File(new File(generatedSiteDirectory, locale.toString()), "xdoc"); - } else { - outputDir = new File(generatedSiteDirectory, "xdoc"); - } - outputDir.mkdirs(); - - PluginXdocGenerator generator = new PluginXdocGenerator( - getProject(), locale, getReportOutputDirectory(), disableInternalJavadocLinkValidation); - PluginToolsRequest pluginToolsRequest = new DefaultPluginToolsRequest(getProject(), pluginDescriptor); - generator.execute(outputDir, pluginToolsRequest); - } catch (GeneratorException e) { - throw new MavenReportException("Error writing plugin documentation", e); - } - } - - /** - * Generates an overview page with the list of goals - * and a link to the goal's page. - */ - static class PluginOverviewRenderer extends AbstractMavenReportRenderer { - private final I18N i18n; - - private final Locale locale; - - private final MavenProject project; - - private final List requirementsHistories; - - private final PluginDescriptor pluginDescriptor; - - private final boolean hasExtensionsToLoad; - - /** - * @param sink not null - * @param i18n not null - * @param locale not null - * @param project not null - * @param requirementsHistories not null - * @param pluginDescriptor not null - */ - PluginOverviewRenderer( - Sink sink, - I18N i18n, - Locale locale, - MavenProject project, - List requirementsHistories, - PluginDescriptor pluginDescriptor, - boolean hasExtensionsToLoad) { - super(sink); - - this.i18n = i18n; - - this.locale = locale; - - this.project = project; - - this.requirementsHistories = requirementsHistories; - - this.pluginDescriptor = pluginDescriptor; - - this.hasExtensionsToLoad = hasExtensionsToLoad; - } - - @Override - public String getTitle() { - return getI18nString("title"); - } - - /** - * @param key The key. - * @return The translated string. - */ - protected String getI18nString(String key) { - return i18n.getString("plugin-report", locale, "report.plugin." + key); - } - - /** - * {@inheritDoc} - */ - @Override - protected void renderBody() { - startSection(getTitle()); - - if (!(pluginDescriptor.getMojos() != null - && pluginDescriptor.getMojos().size() > 0)) { - paragraph(getI18nString("goals.nogoal")); - endSection(); - return; - } - - paragraph(getI18nString("goals.intro")); - - boolean hasMavenReport = false; - for (MojoDescriptor mojo : pluginDescriptor.getMojos()) { - if (GeneratorUtils.isMavenReport(mojo.getImplementation(), project)) { - hasMavenReport = true; - } - } - - startTable(); - - String goalColumnName = getI18nString("goals.column.goal"); - String isMavenReport = getI18nString("goals.column.isMavenReport"); - String descriptionColumnName = getI18nString("goals.column.description"); - if (hasMavenReport) { - tableHeader(new String[] {goalColumnName, isMavenReport, descriptionColumnName}); - } else { - tableHeader(new String[] {goalColumnName, descriptionColumnName}); - } - - List mojos = new ArrayList<>(); - mojos.addAll(pluginDescriptor.getMojos()); - PluginUtils.sortMojos(mojos); - for (MojoDescriptor mojo : mojos) { - String goalName = mojo.getFullGoalName(); - - /* - * Added ./ to define a relative path - * @see AbstractMavenReportRenderer#getValidHref(java.lang.String) - */ - String goalDocumentationLink = "./" + mojo.getGoal() + "-mojo.html"; - - String description; - if (StringUtils.isNotEmpty(mojo.getDeprecated())) { - description = "" + getI18nString("goal.deprecated") + " " + mojo.getDeprecated(); - } else if (StringUtils.isNotEmpty(mojo.getDescription())) { - description = mojo.getDescription(); - } else { - description = getI18nString("goal.nodescription"); - } - - sink.tableRow(); - tableCell(createLinkPatternedText(goalName, goalDocumentationLink)); - if (hasMavenReport) { - if (GeneratorUtils.isMavenReport(mojo.getImplementation(), project)) { - tableCell(getI18nString("isReport")); - } else { - tableCell(getI18nString("isNotReport")); - } - } - tableCell(description, true); - sink.tableRow_(); - } - - endTable(); - - startSection(getI18nString("systemrequirements")); - paragraph(getI18nString("systemrequirements.intro")); - - startTable(); - - String maven = discoverMavenRequirement(project, pluginDescriptor); - sink.tableRow(); - tableCell(getI18nString("systemrequirements.maven")); - tableCell((maven != null ? maven : getI18nString("systemrequirements.nominimum"))); - sink.tableRow_(); - - String jdk = discoverJdkRequirement(project, pluginDescriptor); - sink.tableRow(); - tableCell(getI18nString("systemrequirements.jdk")); - tableCell((jdk != null ? jdk : getI18nString("systemrequirements.nominimum"))); - sink.tableRow_(); - - endTable(); - - endSection(); - - renderRequirementsHistories(); - - renderUsageSection(hasMavenReport); - - endSection(); - } - - private void renderRequirementsHistories() { - if (requirementsHistories.isEmpty()) { - return; - } - - startSection(getI18nString("systemrequirements.history")); - paragraph(getI18nString("systemrequirements.history.intro")); - - startTable(); - tableHeader(new String[] { - getI18nString("systemrequirements.history.version"), - getI18nString("systemrequirements.history.maven"), - getI18nString("systemrequirements.history.jdk") - }); - - requirementsHistories.forEach(requirementsHistory -> { - sink.tableRow(); - tableCell(requirementsHistory.getVersion()); - tableCell(requirementsHistory.getMaven()); - tableCell(requirementsHistory.getJdk()); - sink.tableRow_(); - }); - endTable(); - - endSection(); - } - - /** - * Render the section about the usage of the plugin. - * - * @param hasMavenReport If the plugin has a report or not - */ - private void renderUsageSection(boolean hasMavenReport) { - startSection(getI18nString("usage")); - - // Configuration - paragraph(getI18nString("usage.intro")); - - StringBuilder sb = new StringBuilder(); - sb.append("").append(Markup.EOL); - sb.append(" ...").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ") - .append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ") - .append(pluginDescriptor.getGroupId()) - .append("") - .append(Markup.EOL); - sb.append(" ") - .append(pluginDescriptor.getArtifactId()) - .append("") - .append(Markup.EOL); - sb.append(" ") - .append(pluginDescriptor.getVersion()) - .append("") - .append(Markup.EOL); - if (hasExtensionsToLoad) { - sb.append(" true").append(Markup.EOL); - } - sb.append(" ").append(Markup.EOL); - sb.append(" ...").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ") - .append(pluginDescriptor.getGroupId()) - .append("") - .append(Markup.EOL); - sb.append(" ") - .append(pluginDescriptor.getArtifactId()) - .append("") - .append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ...").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - - if (hasMavenReport) { - sb.append(" ...").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ") - .append(pluginDescriptor.getGroupId()) - .append("") - .append(Markup.EOL); - sb.append(" ") - .append(pluginDescriptor.getArtifactId()) - .append("") - .append(Markup.EOL); - sb.append(" ") - .append(pluginDescriptor.getVersion()) - .append("") - .append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ...").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - sb.append(" ").append(Markup.EOL); - } - - sb.append(" ...").append(Markup.EOL); - sb.append(""); - - verbatimText(sb.toString()); - - sink.paragraph(); - linkPatternedText(getI18nString("configuration.end")); - sink.paragraph_(); - - endSection(); - } - - /** - * Tries to determine the Maven requirement from either the plugin descriptor or (if not set) from the - * Maven prerequisites element in the POM. - * - * @param project not null - * @param pluginDescriptor the plugin descriptor (not null) - * @return the Maven version or null if not specified - */ - private static String discoverMavenRequirement(MavenProject project, PluginDescriptor pluginDescriptor) { - if (StringUtils.isNotBlank(pluginDescriptor.getRequiredMavenVersion())) { - return pluginDescriptor.getRequiredMavenVersion(); - } - return Optional.ofNullable(project.getPrerequisites()) - .map(Prerequisites::getMaven) - .orElse(null); - } - - /** - * Tries to determine the JDK requirement from the following sources (until one is found) - *
      - *
    1. use JDK requirement from plugin descriptor
    2. - *
    3. use {@code release} configuration of {@code org.apache.maven.plugins:maven-compiler-plugin}
    4. - *
    5. use {@code maven.compiler.release<} property
    6. - *
    7. use {@code target} configuration of {@code org.apache.maven.plugins:maven-compiler-plugin}
    8. - *
    9. use {@code maven.compiler.target} property
    10. - *
    - * - * @param project not null - * @param pluginDescriptor the plugin descriptor (not null) - * @return the JDK version - */ - private static String discoverJdkRequirement(MavenProject project, PluginDescriptor pluginDescriptor) { - String jdk = null; - if (pluginDescriptor instanceof ExtendedPluginDescriptor) { - ExtendedPluginDescriptor extPluginDescriptor = (ExtendedPluginDescriptor) pluginDescriptor; - jdk = extPluginDescriptor.getRequiredJavaVersion(); - } - if (jdk != null) { - return jdk; - } - Plugin compiler = getCompilerPlugin(project.getBuild().getPluginsAsMap()); - if (compiler == null) { - compiler = getCompilerPlugin(project.getPluginManagement().getPluginsAsMap()); - } - - jdk = getPluginParameter(compiler, "release"); - if (jdk != null) { - return jdk; - } - - jdk = project.getProperties().getProperty("maven.compiler.release"); - if (jdk != null) { - return jdk; - } - - jdk = getPluginParameter(compiler, "target"); - if (jdk != null) { - return jdk; - } - - // default value - jdk = project.getProperties().getProperty("maven.compiler.target"); - if (jdk != null) { - return jdk; - } - - String version = (compiler == null) ? null : compiler.getVersion(); - - if (version != null) { - return "Default target for maven-compiler-plugin version " + version; - } - - return null; - } - - private static Plugin getCompilerPlugin(Map pluginsAsMap) { - return pluginsAsMap.get("org.apache.maven.plugins:maven-compiler-plugin"); - } - - private static String getPluginParameter(Plugin plugin, String parameter) { - if (plugin != null) { - Xpp3Dom pluginConf = (Xpp3Dom) plugin.getConfiguration(); - - if (pluginConf != null) { - Xpp3Dom target = pluginConf.getChild(parameter); - - if (target != null) { - return target.getValue(); - } + if (pluginDescriptor.getMojos() != null) { + for (MojoDescriptor descriptor : pluginDescriptor.getMojos()) { + GoalRenderer renderer; + try { + String filename = descriptor.getGoal() + "-mojo.html"; + Sink sink = getSinkFactory().createSink(outputDirectory, filename); + renderer = new GoalRenderer( + sink, + i18n, + locale, + project, + descriptor, + outputDirectory, + disableInternalJavadocLinkValidation, + getLog()); + } catch (IOException e) { + throw new MavenReportException("Can not generate sink for mojo " + descriptor.getGoal(), e); } + renderer.render(); } - - return null; } } } diff --git a/maven-plugin-report-plugin/src/main/resources/plugin-report.properties b/maven-plugin-report-plugin/src/main/resources/plugin-report.properties index a483e7a02..fa0989cbd 100644 --- a/maven-plugin-report-plugin/src/main/resources/plugin-report.properties +++ b/maven-plugin-report-plugin/src/main/resources/plugin-report.properties @@ -26,8 +26,49 @@ report.plugin.goals.intro=Goals available for this plugin: report.plugin.goals.column.goal=Goal report.plugin.goals.column.isMavenReport=Report? report.plugin.goals.column.description=Description + report.plugin.goal.nodescription=No description. report.plugin.goal.deprecated=Deprecated. +report.plugin.goal.notice.prefix=Note +report.plugin.goal.notice.isMavenReport=This goal should be used as a Maven report. +report.plugin.goal.fullname=Full name +report.plugin.goal.description=Description +report.plugin.goal.attributes=Attributes +report.plugin.goal.projectRequired=Requires a Maven project to be executed +report.plugin.goal.aggregator=Executes as an aggregator goal +report.plugin.goal.directInvocationOnly=Executes by direct invocation only +report.plugin.goal.reportingMojo=Executes only as a reportSet (reporting goal) +report.plugin.goal.dependencyResolutionRequired=Requires dependency resolution of artifacts in scope +report.plugin.goal.dependencyCollectionRequired=Requires dependency collection of artifacts in scope +report.plugin.goal.since=Since version +report.plugin.goal.phase=Binds by default to the {lifecycle phase, https://maven.apache.org/ref/current/maven-core/lifecycles.html} +report.plugin.goal.threadSafe=The goal is thread-safe and supports parallel builds +report.plugin.goal.notThreadSafe=The goal is not marked as thread-safe and thus does not support parallel builds +report.plugin.goal.executePhase=Invokes the execution of the following {lifecycle phase, https://maven.apache.org/ref/current/maven-core/lifecycles.html} prior to executing itself +report.plugin.goal.executeGoal=Invokes the execution of the following plugin's goal prior to executing itself +report.plugin.goal.executeLifecycle=Executes in its own lifecycle +report.plugin.goal.onlineRequired=Requires that Maven runs in online mode +report.plugin.goal.notInheritedByDefault=Is NOT inherited by default in multi-project builds + +report.plugin.goal.parameters=Parameters +report.plugin.goal.noParameter=(no parameters) +report.plugin.goal.requiredParameters=Required Parameters +report.plugin.goal.optionalParameters=Optional Parameters + +report.plugin.goal.parameter.name.header=Name +report.plugin.goal.parameter.description.header=Description +report.plugin.goal.parameter.type.header=Type +report.plugin.goal.parameter.since.header=Since +report.plugin.goal.parameter.name=<{0}> +report.plugin.goal.parameter.defaultValue=Default +report.plugin.goal.parameter.property=User Property +report.plugin.goal.parameter.alias=Alias +report.plugin.goal.parameter.deprecated=Deprecated. {0} +report.plugin.goal.parameter.type=Type +report.plugin.goal.parameter.required=Required +report.plugin.goal.parameter.expression=Expression +report.plugin.goal.parameter.details=Parameter Details +report.plugin.goal.parameter.since=Since report.plugin.systemrequirements=System Requirements report.plugin.systemrequirements.intro=The following specifies the minimum requirements to run this Maven plugin: @@ -49,3 +90,5 @@ report.plugin.configuration.end=For more information, see {"Guide to Configuring report.plugin.isReport=Yes report.plugin.isNotReport=No +report.plugin.yes=Yes +report.plugin.no=No diff --git a/maven-plugin-report-plugin/src/test/java/org/apache/maven/plugin/plugin/report/GoalRendererTest.java b/maven-plugin-report-plugin/src/test/java/org/apache/maven/plugin/plugin/report/GoalRendererTest.java new file mode 100644 index 000000000..0801d71e3 --- /dev/null +++ b/maven-plugin-report-plugin/src/test/java/org/apache/maven/plugin/plugin/report/GoalRendererTest.java @@ -0,0 +1,64 @@ +/* + * 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.plugin.plugin.report; + +import java.io.File; +import java.util.Locale; + +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class GoalRendererTest { + + @Test + void testGetShortType() { + assertEquals("String", GoalRenderer.getShortType("java.lang.String")); + assertEquals("List", GoalRenderer.getShortType("java.util.List")); + assertEquals( + "Map", GoalRenderer.getShortType("java.util.Map")); + assertEquals("List<...>", GoalRenderer.getShortType("java.util.List>")); + } + + @Test + void testGetXhtmlWithValidatedLinks() { + File baseDir = new File(this.getClass().getResource("").getFile()); + GoalRenderer renderer = + new GoalRenderer(null, null, Locale.ROOT, null, null, baseDir, false, new SystemStreamLog()); + GoalRenderer rendererWithDisabledLinkValidator = + new GoalRenderer(null, null, Locale.ROOT, null, null, baseDir, true, new SystemStreamLog()); + String externalLink = + "testExternal Link..and a secondlinkend"; + assertEquals(externalLink, renderer.getXhtmlWithValidatedLinks(externalLink, "test")); + assertEquals(externalLink, renderer.getXhtmlWithValidatedLinks(externalLink, "test")); + String validInternalLink = + "testInternal Link..and a secondlinkend"; + assertEquals(validInternalLink, renderer.getXhtmlWithValidatedLinks(validInternalLink, "test")); + assertEquals(validInternalLink, renderer.getXhtmlWithValidatedLinks(validInternalLink, "test")); + String invalidInternalLink = + "testInternal Link..and a secondlinkend"; + String sanitizedInvalidInternalLink = + "testInternal Link..and a secondlinkend"; + assertEquals(sanitizedInvalidInternalLink, renderer.getXhtmlWithValidatedLinks(invalidInternalLink, "test")); + assertEquals( + invalidInternalLink, + rendererWithDisabledLinkValidator.getXhtmlWithValidatedLinks(invalidInternalLink, "test")); + } +} diff --git a/maven-plugin-tools-api/pom.xml b/maven-plugin-tools-api/pom.xml index 520255a99..247b3dc7a 100644 --- a/maven-plugin-tools-api/pom.xml +++ b/maven-plugin-tools-api/pom.xml @@ -53,6 +53,10 @@ org.slf4j slf4j-api
    + + org.apache.maven.reporting + maven-reporting-api + org.codehaus.plexus @@ -101,6 +105,16 @@ slf4j-simple test + + org.apache.maven.reporting + maven-reporting-impl + test + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + test + diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java index 8ca9e7e4a..4aa62ae7f 100644 --- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java +++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/util/PluginUtils.java @@ -18,14 +18,22 @@ */ package org.apache.maven.tools.plugin.util; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.MavenReport; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; @@ -137,4 +145,50 @@ public int compare(Parameter parameter1, Parameter parameter2) { }); } } + + /** + * @param mojoClassName a fully qualified Mojo implementation class name, not null + * @param project a MavenProject instance, could be null + * @return true if the Mojo class implements MavenReport, + * false otherwise. + * @throws IllegalArgumentException if any + * @since 3.10.0 + */ + public static boolean isMavenReport(String mojoClassName, MavenProject project) throws IllegalArgumentException { + if (mojoClassName == null) { + throw new IllegalArgumentException("mojo implementation should be declared"); + } + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (project != null) { + List classPathStrings; + try { + classPathStrings = project.getCompileClasspathElements(); + if (project.getExecutionProject() != null) { + classPathStrings.addAll(project.getExecutionProject().getCompileClasspathElements()); + } + } catch (DependencyResolutionRequiredException e) { + throw new IllegalArgumentException(e); + } + + List urls = new ArrayList<>(classPathStrings.size()); + for (String classPathString : classPathStrings) { + try { + urls.add(new File(classPathString).toURL()); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } + + classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), classLoader); + } + + try { + Class clazz = Class.forName(mojoClassName, false, classLoader); + + return MavenReport.class.isAssignableFrom(clazz); + } catch (ClassNotFoundException e) { + return false; + } + } } diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/PluginUtilsTest.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/PluginUtilsTest.java index 3330f19d7..bbd2081e2 100644 --- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/PluginUtilsTest.java +++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/PluginUtilsTest.java @@ -18,10 +18,15 @@ */ package org.apache.maven.tools.plugin.util; +import java.util.Collections; + import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.testing.stubs.MavenProjectStub; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author jdcasey @@ -61,4 +66,23 @@ void testShouldFindOneScriptsWhenAnExcludeIsGiven() { String[] files = PluginUtils.findSources(basedir, includes, excludes); assertEquals(1, files.length); } + + @Test + void testIsMavenReport() throws Exception { + try { + PluginUtils.isMavenReport(null, null); + } catch (IllegalArgumentException e) { + assertTrue(true); + } + + String impl = "org.apache.maven.tools.plugin.util.stubs.MavenReportStub"; + + MavenProjectStub stub = new MavenProjectStub(); + stub.setCompileSourceRoots(Collections.singletonList(System.getProperty("basedir") + "/target/classes")); + + assertTrue(PluginUtils.isMavenReport(impl, stub)); + + impl = "org.apache.maven.tools.plugin.util.stubs.MojoStub"; + assertFalse(PluginUtils.isMavenReport(impl, stub)); + } } diff --git a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/stubs/MavenReportStub.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/stubs/MavenReportStub.java similarity index 97% rename from maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/stubs/MavenReportStub.java rename to maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/stubs/MavenReportStub.java index 855284f81..0358de025 100644 --- a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/stubs/MavenReportStub.java +++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/util/stubs/MavenReportStub.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.maven.tools.plugin.generator.stubs; +package org.apache.maven.tools.plugin.util.stubs; import java.util.Locale; diff --git a/maven-plugin-tools-generators/pom.xml b/maven-plugin-tools-generators/pom.xml index 1198e807d..7093d0c3f 100644 --- a/maven-plugin-tools-generators/pom.xml +++ b/maven-plugin-tools-generators/pom.xml @@ -44,11 +44,6 @@ maven-model - - org.apache.maven.reporting - maven-reporting-api - - org.codehaus.plexus @@ -98,16 +93,6 @@ plexus-testing test - - org.apache.maven.reporting - maven-reporting-impl - test - - - org.apache.maven.plugin-testing - maven-plugin-testing-harness - test - org.slf4j slf4j-simple diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorUtils.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorUtils.java index 99aa7965c..c97798702 100644 --- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorUtils.java +++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/GeneratorUtils.java @@ -25,14 +25,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.io.StringReader; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; @@ -43,11 +38,10 @@ import java.util.regex.Pattern; import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.project.MavenProject; -import org.apache.maven.reporting.MavenReport; +import org.apache.maven.tools.plugin.util.PluginUtils; import org.codehaus.plexus.component.repository.ComponentDependency; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.XMLWriter; @@ -557,43 +551,10 @@ public static String discoverPackageName(PluginDescriptor pluginDescriptor) { * @return true is the Mojo implementation implements MavenReport, * false otherwise. * @throws IllegalArgumentException if any + * @deprecated Use {@link PluginUtils#isMavenReport(String, MavenProject)} instead. */ - @SuppressWarnings("unchecked") + @Deprecated public static boolean isMavenReport(String impl, MavenProject project) throws IllegalArgumentException { - if (impl == null) { - throw new IllegalArgumentException("mojo implementation should be declared"); - } - - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (project != null) { - List classPathStrings; - try { - classPathStrings = project.getCompileClasspathElements(); - if (project.getExecutionProject() != null) { - classPathStrings.addAll(project.getExecutionProject().getCompileClasspathElements()); - } - } catch (DependencyResolutionRequiredException e) { - throw new IllegalArgumentException(e); - } - - List urls = new ArrayList<>(classPathStrings.size()); - for (String classPathString : classPathStrings) { - try { - urls.add(new File(classPathString).toURL()); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(e); - } - } - - classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), classLoader); - } - - try { - Class clazz = Class.forName(impl, false, classLoader); - - return MavenReport.class.isAssignableFrom(clazz); - } catch (ClassNotFoundException e) { - return false; - } + return PluginUtils.isMavenReport(impl, project); } } diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java index 7a0d9335c..3f44f034d 100644 --- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java +++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java @@ -54,7 +54,7 @@ *
  • a standard Maven Plugin Descriptor XML file
  • *
  • a descriptor containing a limited set of elements for {@link PluginHelpGenerator}
  • *
  • an enhanced descriptor containing HTML values for some elements (instead of plain text as for the other two) - * for {@link PluginXdocGenerator}
  • + * for {@code org.apache.maven.plugin.plugin.report.GoalRenderer} * * from a given in-memory descriptor. The in-memory descriptor acting as source is supposed to contain XHTML values * for description elements. diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java deleted file mode 100644 index 047355c75..000000000 --- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java +++ /dev/null @@ -1,812 +0,0 @@ -/* - * 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 xdoc documentation 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("(.*?)"); - - 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 Locale.ENGLISH as locale. - * Used only in test cases. - */ - public PluginXdocGenerator() { - this(null); - } - - /** - * Constructor using Locale.ENGLISH 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 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().getId() + ":" + 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 parameterList = mojoDescriptor.getParameters(); - - // remove components and read-only parameters - List 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 filterParameters(List parameterList) { - List 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 parameterList, XMLWriter w, String goal) { - w.startElement("subsection"); - w.addAttribute("name", getString("pluginxdoc.mojodescriptor.parameter.details")); - - for (Iterator 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("
    "); - } - } - - 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 parameterList, XMLWriter w, String goal) { - List requiredParams = getParametersByRequired(true, parameterList); - if (!requiredParams.isEmpty()) { - writeParameterList(getString("pluginxdoc.mojodescriptor.requiredParameters"), requiredParams, w, goal); - } - - List 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 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("" + getLinkedType(parameter, true) + ""); - w.endElement(); // td - - // since - w.startElement("td"); - if (StringUtils.isNotEmpty(parameter.getSince())) { - w.writeMarkup("" + parameter.getSince() + ""); - } else { - w.writeMarkup("-"); - } - 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 + "
    "); - - if (StringUtils.isNotEmpty(parameter.getDefaultValue())) { - w.writeMarkup(format( - "pluginxdoc.mojodescriptor.parameter.defaultValue", escapeXml(parameter.getDefaultValue()))); - w.writeMarkup("
    "); - } - - String property = getPropertyFromExpression(parameter.getExpression()); - if (property != null) { - w.writeMarkup(format("pluginxdoc.mojodescriptor.parameter.property.description", property)); - w.writeMarkup("
    "); - } - - 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 true for required parameters, false otherwise. - * @param parameterList not null - * @return list of parameters depending the value of required - */ - private List getParametersByRequired(boolean required, List parameterList) { - List list = new ArrayList<>(); - - for (Parameter parameter : parameterList) { - if (parameter.isRequired() == required) { - list.add(parameter); - } - } - - return list; - } - - /** - * Gets the resource bundle for the locale instance variable. - * - * @return The resource bundle for the locale instance variable. - */ - private ResourceBundle getBundle() { - return ResourceBundle.getBundle("pluginxdoc", locale, getClass().getClassLoader()); - } - - /** - * @param key not null - * @return Localized, text identified by key. - * @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 key. - * @see #format(String, Object[]) - */ - private String format(String key, Object arg1) { - return format(key, new Object[] {arg1}); - } - - /** - * Looks up the value for key in the ResourceBundle, - * then formats that value for the specified Locale using args. - * - * @param key not null - * @param args not null - * @return Localized, formatted text identified by key. - */ - 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("&", "&"); - text = text.replace("<", "<"); - text = text.replace(">", ">"); - text = text.replace("\"", """); - text = text.replace("\'", "'"); - } - 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(); - } -} diff --git a/maven-plugin-tools-generators/src/main/resources/pluginxdoc.properties b/maven-plugin-tools-generators/src/main/resources/pluginxdoc.properties deleted file mode 100644 index 2bda11abf..000000000 --- a/maven-plugin-tools-generators/src/main/resources/pluginxdoc.properties +++ /dev/null @@ -1,64 +0,0 @@ -# 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. - -pluginxdoc.yes=Yes -pluginxdoc.no=No -pluginxdoc.detail={0}: {1} - -pluginxdoc.description=Description: -pluginxdoc.nodescription=(no description) -pluginxdoc.mojodescriptor.notice.note=Note: -pluginxdoc.mojodescriptor.notice.isMavenReport=This goal should be used as a Maven report. -pluginxdoc.mojodescriptor.fullname=Full name: -pluginxdoc.mojodescriptor.attributes=Attributes: -pluginxdoc.mojodescriptor.deprecated=This plugin goal has been deprecated: -pluginxdoc.mojodescriptor.projectRequired=Requires a Maven project to be executed. -pluginxdoc.mojodescriptor.aggregator=Executes as an aggregator goal. -pluginxdoc.mojodescriptor.directInvocationOnly=Executes by direct invocation only. -pluginxdoc.mojodescriptor.reportingMojo=Executes only as a reportSet (reporting goal). -pluginxdoc.mojodescriptor.dependencyResolutionRequired=Requires dependency resolution of artifacts in scope: {0}. -pluginxdoc.mojodescriptor.dependencyCollectionRequired=Requires dependency collection of artifacts in scope: {0}. -pluginxdoc.mojodescriptor.since=Since version: {0} -pluginxdoc.mojodescriptor.phase=Binds by default to the lifecycle phase: {0}. -pluginxdoc.mojodescriptor.executePhase=Invokes the execution of the lifecycle phase {0} prior to executing itself. -pluginxdoc.mojodescriptor.executeGoal=Invokes the execution of this plugin's goal {0} prior to executing itself. -pluginxdoc.mojodescriptor.executeLifecycle=Executes in its own lifecycle: {0}. -pluginxdoc.mojodescriptor.onlineRequired=Requires that Maven runs in online mode. -pluginxdoc.mojodescriptor.inheritedByDefault=Is NOT inherited by default in multi-project builds. -pluginxdoc.mojodescriptor.parameter.details=Parameter Details -pluginxdoc.mojodescriptor.parameter.deprecated=Deprecated. {0} -pluginxdoc.mojodescriptor.parameter.name=Name -pluginxdoc.mojodescriptor.parameter.name_link=<{0}> -pluginxdoc.mojodescriptor.parameter.name_internal=<{0}> -pluginxdoc.mojodescriptor.parameter.description=Description -pluginxdoc.mojodescriptor.parameter.type=Type -pluginxdoc.mojodescriptor.parameter.type_link={0} -pluginxdoc.mojodescriptor.parameter.since=Since -pluginxdoc.mojodescriptor.parameter.required=Required -pluginxdoc.mojodescriptor.parameter.expression=Expression -pluginxdoc.mojodescriptor.parameter.property=User Property -pluginxdoc.mojodescriptor.parameter.property.description=User property: {0} -pluginxdoc.mojodescriptor.parameter.default=Default -pluginxdoc.mojodescriptor.parameter.defaultValue=Default value: {0} -pluginxdoc.mojodescriptor.parameter.alias=Alias -pluginxdoc.mojodescriptor.parameter.alias.description=Alias: {0} -pluginxdoc.mojodescriptor.requiredParameters=Required Parameters -pluginxdoc.mojodescriptor.optionalParameters=Optional Parameters -pluginxdoc.mojodescriptor.parameters=Parameters -pluginxdoc.mojodescriptor.noParameter=(no parameters) -pluginxdoc.mojodescriptor.threadSafe=The goal is thread-safe and supports parallel builds. -pluginxdoc.mojodescriptor.notThreadSafe=The goal is not marked as thread-safe and thus does not support parallel builds. diff --git a/maven-plugin-tools-generators/src/main/resources/pluginxdoc_de.properties b/maven-plugin-tools-generators/src/main/resources/pluginxdoc_de.properties deleted file mode 100644 index c326151e2..000000000 --- a/maven-plugin-tools-generators/src/main/resources/pluginxdoc_de.properties +++ /dev/null @@ -1,56 +0,0 @@ -# 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. - -pluginxdoc.yes=Ja -pluginxdoc.no=Nein - -pluginxdoc.description=Beschreibung: -pluginxdoc.nodescription=(keine Beschreibung) -pluginxdoc.mojodescriptor.notice.note=Anmerkung: -pluginxdoc.mojodescriptor.notice.isMavenReport=Dieses Goal erzeugt einen Maven-Bericht. -pluginxdoc.mojodescriptor.fullname=Vollst\u00e4ndiger Name: -pluginxdoc.mojodescriptor.attributes=Attribute: -pluginxdoc.mojodescriptor.deprecated=Dieses Plugin-Goal ist missbilligt: -pluginxdoc.mojodescriptor.projectRequired=Erfordert ein Maven Projekt zur Ausf\u00fchrung. -pluginxdoc.mojodescriptor.aggregator=Wird als Aggregator ausgef\u00fchrt. -pluginxdoc.mojodescriptor.directInvocationOnly=Wird nur per direktem Aufruf ausgef\u00fchrt. -pluginxdoc.mojodescriptor.dependencyResolutionRequired=Erfordert Abh\u00e4ngigkeitsaufl\u00f6sung von Artefakten mit Geltungsbereich: {0}. -pluginxdoc.mojodescriptor.dependencyCollectionRequired=Erfordert Abh\u00e4ngigkeitsermittlung von Artefakten mit Geltungsbereich: {0}. -pluginxdoc.mojodescriptor.since=Seit Version: {0}. -pluginxdoc.mojodescriptor.phase=Bindet automatisch an die Lebenszyklusphase: {0}. -pluginxdoc.mojodescriptor.executePhase=Bedingt die Ausf\u00fchrung der Lebenszyklusphase {0} vor seiner eigenen Ausf\u00fchrung. -pluginxdoc.mojodescriptor.executeGoal=Bedingt die Ausf\u00fchrung des Plugin-Goals {0} vor seiner eigenen Ausf\u00fchrung. -pluginxdoc.mojodescriptor.executeLifecycle=Wird in seinem eigenen Lebenszyklus ausgef\u00fchrt: {0}. -pluginxdoc.mojodescriptor.onlineRequired=Erfordert die Ausf\u00fchrung von Maven im Online-Modus. -pluginxdoc.mojodescriptor.inheritedByDefault=Wird bei einem Multi-Projekt-Build standardm\u00e4\u00dfig nicht vererbt. -pluginxdoc.mojodescriptor.parameter.details=Parameter-Details -pluginxdoc.mojodescriptor.parameter.deprecated=Missbilligt. {0} -pluginxdoc.mojodescriptor.parameter.name=Name -pluginxdoc.mojodescriptor.parameter.description=Beschreibung -pluginxdoc.mojodescriptor.parameter.type=Typ -pluginxdoc.mojodescriptor.parameter.since=Seit -pluginxdoc.mojodescriptor.parameter.required=Erforderlich -pluginxdoc.mojodescriptor.parameter.expression=Ausdruck -pluginxdoc.mojodescriptor.parameter.default=Standard -pluginxdoc.mojodescriptor.parameter.defaultValue=Standardwert ist: {0}. -pluginxdoc.mojodescriptor.parameter.alias=Alias -pluginxdoc.mojodescriptor.parameter.alias.description=Alias ist: {0}. -pluginxdoc.mojodescriptor.requiredParameters=Erforderliche Parameter -pluginxdoc.mojodescriptor.optionalParameters=Optionale Parameter -pluginxdoc.mojodescriptor.parameters=Parameter -pluginxdoc.mojodescriptor.noParameter=(keine Parameter) -pluginxdoc.mojodescriptor.threadSafe=Dieses Goal is thread-sicher und unterst\u00fctzt paralleles Bauen. diff --git a/maven-plugin-tools-generators/src/main/resources/pluginxdoc_en.properties b/maven-plugin-tools-generators/src/main/resources/pluginxdoc_en.properties deleted file mode 100644 index 96cf40750..000000000 --- a/maven-plugin-tools-generators/src/main/resources/pluginxdoc_en.properties +++ /dev/null @@ -1,23 +0,0 @@ -# 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. - -# NOTE: -# This bundle is intentionally empty because English strings are provided by the base bundle via the parent chain. It -# must be provided nevertheless such that a request for locale "en" will not errorneously pick up the bundle for the -# JVM's default locale (which need not be "en"). See the method javadoc about -# ResourceBundle.getBundle(String, Locale, ClassLoader) -# for a full description of the lookup strategy. diff --git a/maven-plugin-tools-generators/src/main/resources/pluginxdoc_fr.properties b/maven-plugin-tools-generators/src/main/resources/pluginxdoc_fr.properties deleted file mode 100644 index a687851d4..000000000 --- a/maven-plugin-tools-generators/src/main/resources/pluginxdoc_fr.properties +++ /dev/null @@ -1,60 +0,0 @@ -# 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. - -pluginxdoc.yes=Oui -pluginxdoc.no=Non -pluginxdoc.detail={0} : {1} - -pluginxdoc.description=Description : -pluginxdoc.nodescription=(aucune description) -pluginxdoc.mojodescriptor.notice.note=Note : -pluginxdoc.mojodescriptor.notice.isMavenReport=Ce goal doit \u00eatre utilis\u00e9 comme un rapport de Maven. -pluginxdoc.mojodescriptor.fullname=Nom complet : -pluginxdoc.mojodescriptor.attributes=Attributs : -pluginxdoc.mojodescriptor.deprecated=Le goal de ce plugin est obsol\u00e8te : -pluginxdoc.mojodescriptor.projectRequired=Exige un projet Maven pour \u00eatre ex\u00e9cut\u00e9. -pluginxdoc.mojodescriptor.aggregator=S'ex\u00e9cute comme un goal agr\u00e9g\u00e9. -pluginxdoc.mojodescriptor.directInvocationOnly=S'ex\u00e9cute par l'invocation directe seulement. -pluginxdoc.mojodescriptor.reportingMojo=S'ex\u00e9cute seulement comme un reportSet (goal de reporting). -pluginxdoc.mojodescriptor.dependencyResolutionRequired=Exige une r\u00e9solution des d\u00e9pendances des artefacts dans le scope : {0}. -pluginxdoc.mojodescriptor.dependencyCollectionRequired=Exige une collecte des d\u00e9pendances des artefacts dans le scope : {0}. -pluginxdoc.mojodescriptor.since=Depuis la version : {0}. -pluginxdoc.mojodescriptor.phase=S'associe par d\u00e9faut dans la phase du cycle de vie : {0}. -pluginxdoc.mojodescriptor.executePhase=Appelle l'ex\u00e9cution de la phase du cycle de vie {0} avant de s'ex\u00e9cuter. -pluginxdoc.mojodescriptor.executeGoal=Appelle l'ex\u00e9cution du goal de ce plugin {0} avant de s'ex\u00e9cuter. -pluginxdoc.mojodescriptor.executeLifecycle=S'ex\u00e9cute dans son propre cycle de vie : {0}. -pluginxdoc.mojodescriptor.onlineRequired=Exige que Maven s'ex\u00e9cute en ligne. -pluginxdoc.mojodescriptor.inheritedByDefault=N'est PAS h\u00e9rit\u00e9 par d\u00e9faut dans une construction multi-projet. -pluginxdoc.mojodescriptor.parameter.details=D\u00e9tails des param\u00e8tres -pluginxdoc.mojodescriptor.parameter.deprecated=Obsol\u00e8te. {0} -pluginxdoc.mojodescriptor.parameter.name=Nom -pluginxdoc.mojodescriptor.parameter.description=Description -pluginxdoc.mojodescriptor.parameter.type=Type -pluginxdoc.mojodescriptor.parameter.since=Depuis -pluginxdoc.mojodescriptor.parameter.required=Exig\u00e9 -pluginxdoc.mojodescriptor.parameter.expression=Expression -pluginxdoc.mojodescriptor.parameter.property=Propri\u00e9t\u00e9 utilisateur -pluginxdoc.mojodescriptor.parameter.property.description=Propri\u00e9t\u00e9 utilisateur : {0}. -pluginxdoc.mojodescriptor.parameter.default=D\u00e9faut -pluginxdoc.mojodescriptor.parameter.defaultValue=Valeur par d\u00e9faut : {0}. -pluginxdoc.mojodescriptor.parameter.alias=Alias -pluginxdoc.mojodescriptor.parameter.alias.description=Alias : {0}. -pluginxdoc.mojodescriptor.requiredParameters=Param\u00e8tres requis -pluginxdoc.mojodescriptor.optionalParameters=Param\u00e8tres optionnels -pluginxdoc.mojodescriptor.parameters=Param\u00e8tres -pluginxdoc.mojodescriptor.noParameter=(aucun param\u00e8tre) -pluginxdoc.mojodescriptor.threadSafe=Le goal est thread-safe et supporte des constructions parall\u00e8les. diff --git a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/GeneratorUtilsTest.java b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/GeneratorUtilsTest.java index 86aa0594e..d0e10c8e2 100644 --- a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/GeneratorUtilsTest.java +++ b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/GeneratorUtilsTest.java @@ -26,15 +26,12 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.plugin.descriptor.PluginDescriptor; -import org.apache.maven.plugin.testing.stubs.MavenProjectStub; import org.codehaus.plexus.component.repository.ComponentDependency; import org.codehaus.plexus.util.xml.CompactXMLWriter; import org.codehaus.plexus.util.xml.XMLWriter; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author jdcasey @@ -185,25 +182,6 @@ void testToText() throws Exception { // assertEquals( "Generates something for the project.", GeneratorUtils.toText( javadoc ) ); } - @Test - void testIsMavenReport() throws Exception { - try { - GeneratorUtils.isMavenReport(null, null); - } catch (IllegalArgumentException e) { - assertTrue(true); - } - - String impl = "org.apache.maven.tools.plugin.generator.stubs.MavenReportStub"; - - MavenProjectStub stub = new MavenProjectStub(); - stub.setCompileSourceRoots(Collections.singletonList(System.getProperty("basedir") + "/target/classes")); - - assertTrue(GeneratorUtils.isMavenReport(impl, stub)); - - impl = "org.apache.maven.tools.plugin.util.stubs.MojoStub"; - assertFalse(GeneratorUtils.isMavenReport(impl, stub)); - } - @Test void testExcludeProvidedScopeFormComponentDependencies() { diff --git a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java deleted file mode 100644 index 5d6cd6956..000000000 --- a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.InputStream; -import java.util.Locale; - -import org.codehaus.plexus.util.ReaderFactory; -import org.codehaus.plexus.util.xml.Xpp3Dom; -import org.codehaus.plexus.util.xml.Xpp3DomBuilder; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * @author Jason van Zyl - * @author Vincent Siveton - */ -public class PluginXdocGeneratorTest extends AbstractGeneratorTestCase { - - // inherits tests from base class - - @Override - protected void validate(File destinationDirectory) throws Exception { - File docFile = new File(destinationDirectory, "testGoal-mojo.xml"); - Xpp3Dom actual = Xpp3DomBuilder.build(ReaderFactory.newXmlReader(docFile)); - - InputStream expectedAsStream = getClass().getResourceAsStream("/expected-testGoal-mojo.xml"); - - Xpp3Dom expected = Xpp3DomBuilder.build(ReaderFactory.newXmlReader(expectedAsStream)); - - Assertions.assertEquals(expected, actual); - } - - @Test - void testGetShortType() { - assertEquals("String", PluginXdocGenerator.getShortType("java.lang.String")); - assertEquals("List", PluginXdocGenerator.getShortType("java.util.List")); - assertEquals( - "Map", - PluginXdocGenerator.getShortType("java.util.Map")); - assertEquals("List<...>", PluginXdocGenerator.getShortType("java.util.List>")); - } - - @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 = - "testExternal Link..and a secondlinkend"; - assertEquals(externalLink, xdocGenerator.getXhtmlWithValidatedLinks(externalLink, "test")); - assertEquals( - externalLink, xdocGeneratorWithDisabledLinkValidator.getXhtmlWithValidatedLinks(externalLink, "test")); - String validInternalLink = - "testInternal Link..and a secondlinkend"; - assertEquals(validInternalLink, xdocGenerator.getXhtmlWithValidatedLinks(validInternalLink, "test")); - assertEquals( - validInternalLink, - xdocGeneratorWithDisabledLinkValidator.getXhtmlWithValidatedLinks(validInternalLink, "test")); - String invalidInternalLink = - "testInternal Link..and a secondlinkend"; - String sanitizedInvalidInternalLink = - "testInternal Link..and a secondlinkend"; - assertEquals( - sanitizedInvalidInternalLink, xdocGenerator.getXhtmlWithValidatedLinks(invalidInternalLink, "test")); - assertEquals( - invalidInternalLink, - xdocGeneratorWithDisabledLinkValidator.getXhtmlWithValidatedLinks(invalidInternalLink, "test")); - } -}