1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.tools.plugin.generator;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.OutputStreamWriter;
24 import java.io.PrintWriter;
25 import java.io.Writer;
26 import java.net.URI;
27 import java.net.URISyntaxException;
28 import java.text.MessageFormat;
29 import java.util.ArrayList;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Locale;
33 import java.util.ResourceBundle;
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36
37 import org.apache.maven.plugin.descriptor.MojoDescriptor;
38 import org.apache.maven.plugin.descriptor.Parameter;
39 import org.apache.maven.project.MavenProject;
40 import org.apache.maven.tools.plugin.EnhancedParameterWrapper;
41 import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
42 import org.apache.maven.tools.plugin.PluginToolsRequest;
43 import org.apache.maven.tools.plugin.javadoc.JavadocLinkGenerator;
44 import org.codehaus.plexus.util.StringUtils;
45 import org.codehaus.plexus.util.io.CachingOutputStream;
46 import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
47 import org.codehaus.plexus.util.xml.XMLWriter;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import static java.nio.charset.StandardCharsets.UTF_8;
52
53
54
55
56 public class PluginXdocGenerator implements Generator {
57
58
59
60
61 private static final Pattern HTML_LINK_PATTERN = Pattern.compile("<a href=\\\"([^\\\"]*)\\\">(.*?)</a>");
62
63 private static final Logger LOG = LoggerFactory.getLogger(PluginXdocGenerator.class);
64
65
66
67
68 private final Locale locale;
69
70
71
72
73 private final MavenProject project;
74
75
76
77
78
79 private final File reportOutputDirectory;
80
81 private final boolean disableInternalJavadocLinkValidation;
82
83
84
85
86
87 public PluginXdocGenerator() {
88 this(null);
89 }
90
91
92
93
94
95
96 public PluginXdocGenerator(MavenProject project) {
97 this(project, Locale.ENGLISH, new File("").getAbsoluteFile(), false);
98 }
99
100
101
102
103
104 public PluginXdocGenerator(
105 MavenProject project,
106 Locale locale,
107 File reportOutputDirectory,
108 boolean disableInternalJavadocLinkValidation) {
109 this.project = project;
110 if (locale == null) {
111 this.locale = Locale.ENGLISH;
112 } else {
113 this.locale = locale;
114 }
115 this.reportOutputDirectory = reportOutputDirectory;
116 this.disableInternalJavadocLinkValidation = disableInternalJavadocLinkValidation;
117 }
118
119
120
121
122 @Override
123 public void execute(File destinationDirectory, PluginToolsRequest request) throws GeneratorException {
124 try {
125 if (request.getPluginDescriptor().getMojos() != null) {
126 List<MojoDescriptor> mojos = request.getPluginDescriptor().getMojos();
127 for (MojoDescriptor descriptor : mojos) {
128 processMojoDescriptor(descriptor, destinationDirectory);
129 }
130 }
131 } catch (IOException e) {
132 throw new GeneratorException(e.getMessage(), e);
133 }
134 }
135
136
137
138
139
140
141 protected void processMojoDescriptor(MojoDescriptor mojoDescriptor, File destinationDirectory) throws IOException {
142 File outputFile = new File(destinationDirectory, getMojoFilename(mojoDescriptor, "xml"));
143 try (Writer writer = new OutputStreamWriter(new CachingOutputStream(outputFile), UTF_8)) {
144 XMLWriter w = new PrettyPrintXMLWriter(new PrintWriter(writer), UTF_8.name(), null);
145 writeBody(mojoDescriptor, w);
146
147 writer.flush();
148 }
149 }
150
151
152
153
154
155
156 private String getMojoFilename(MojoDescriptor mojo, String ext) {
157 return mojo.getGoal() + "-mojo." + ext;
158 }
159
160
161
162
163
164 private void writeBody(MojoDescriptor mojoDescriptor, XMLWriter w) {
165 w.startElement("document");
166 w.addAttribute("xmlns", "http://maven.apache.org/XDOC/2.0");
167 w.addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
168 w.addAttribute(
169 "xsi:schemaLocation", "http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd");
170
171
172
173
174
175 w.startElement("properties");
176
177 w.startElement("title");
178 w.writeText(mojoDescriptor.getFullGoalName());
179 w.endElement();
180
181 w.endElement();
182
183
184
185
186
187 w.startElement("body");
188
189 w.startElement("section");
190
191 w.addAttribute("name", mojoDescriptor.getFullGoalName());
192
193 writeReportNotice(mojoDescriptor, w);
194
195 w.startElement("p");
196 w.writeMarkup(getString("pluginxdoc.mojodescriptor.fullname"));
197 w.endElement();
198 w.startElement("p");
199 w.writeMarkup(mojoDescriptor.getPluginDescriptor().getGroupId() + ":"
200 + mojoDescriptor.getPluginDescriptor().getArtifactId() + ":"
201 + mojoDescriptor.getPluginDescriptor().getVersion() + ":" + mojoDescriptor.getGoal());
202 w.endElement();
203
204 String context = "goal " + mojoDescriptor.getGoal();
205 if (StringUtils.isNotEmpty(mojoDescriptor.getDeprecated())) {
206 w.startElement("p");
207 w.writeMarkup(getString("pluginxdoc.mojodescriptor.deprecated"));
208 w.endElement();
209 w.startElement("div");
210 w.writeMarkup(getXhtmlWithValidatedLinks(mojoDescriptor.getDeprecated(), context));
211 w.endElement();
212 }
213
214 w.startElement("p");
215 w.writeMarkup(getString("pluginxdoc.description"));
216 w.endElement();
217 w.startElement("div");
218 if (StringUtils.isNotEmpty(mojoDescriptor.getDescription())) {
219 w.writeMarkup(getXhtmlWithValidatedLinks(mojoDescriptor.getDescription(), context));
220 } else {
221 w.writeText(getString("pluginxdoc.nodescription"));
222 }
223 w.endElement();
224
225 writeGoalAttributes(mojoDescriptor, w);
226
227 writeGoalParameterTable(mojoDescriptor, w);
228
229 w.endElement();
230
231 w.endElement();
232
233 w.endElement();
234 }
235
236
237
238
239
240 private void writeReportNotice(MojoDescriptor mojoDescriptor, XMLWriter w) {
241 if (GeneratorUtils.isMavenReport(mojoDescriptor.getImplementation(), project)) {
242 w.startElement("p");
243 w.writeMarkup(getString("pluginxdoc.mojodescriptor.notice.note"));
244 w.writeText(getString("pluginxdoc.mojodescriptor.notice.isMavenReport"));
245 w.endElement();
246 }
247 }
248
249
250
251
252
253 private void writeGoalAttributes(MojoDescriptor mojoDescriptor, XMLWriter w) {
254 w.startElement("p");
255 w.writeMarkup(getString("pluginxdoc.mojodescriptor.attributes"));
256 w.endElement();
257
258 boolean addedUl = false;
259 String value;
260 if (mojoDescriptor.isProjectRequired()) {
261 addedUl = addUl(w, addedUl);
262 w.startElement("li");
263 w.writeMarkup(getString("pluginxdoc.mojodescriptor.projectRequired"));
264 w.endElement();
265 }
266
267 if (mojoDescriptor.isRequiresReports()) {
268 addedUl = addUl(w, addedUl);
269 w.startElement("li");
270 w.writeMarkup(getString("pluginxdoc.mojodescriptor.reportingMojo"));
271 w.endElement();
272 }
273
274 if (mojoDescriptor.isAggregator()) {
275 addedUl = addUl(w, addedUl);
276 w.startElement("li");
277 w.writeMarkup(getString("pluginxdoc.mojodescriptor.aggregator"));
278 w.endElement();
279 }
280
281 if (mojoDescriptor.isDirectInvocationOnly()) {
282 addedUl = addUl(w, addedUl);
283 w.startElement("li");
284 w.writeMarkup(getString("pluginxdoc.mojodescriptor.directInvocationOnly"));
285 w.endElement();
286 }
287
288 value = mojoDescriptor.isDependencyResolutionRequired();
289 if (StringUtils.isNotEmpty(value)) {
290 addedUl = addUl(w, addedUl);
291 w.startElement("li");
292 w.writeMarkup(format("pluginxdoc.mojodescriptor.dependencyResolutionRequired", value));
293 w.endElement();
294 }
295
296 if (mojoDescriptor instanceof ExtendedMojoDescriptor) {
297 ExtendedMojoDescriptor extendedMojoDescriptor = (ExtendedMojoDescriptor) mojoDescriptor;
298
299 value = extendedMojoDescriptor.getDependencyCollectionRequired();
300 if (StringUtils.isNotEmpty(value)) {
301 addedUl = addUl(w, addedUl);
302 w.startElement("li");
303 w.writeMarkup(format("pluginxdoc.mojodescriptor.dependencyCollectionRequired", value));
304 w.endElement();
305 }
306 }
307
308 addedUl = addUl(w, addedUl);
309 w.startElement("li");
310 w.writeMarkup(getString(
311 mojoDescriptor.isThreadSafe()
312 ? "pluginxdoc.mojodescriptor.threadSafe"
313 : "pluginxdoc.mojodescriptor.notThreadSafe"));
314 w.endElement();
315
316 value = mojoDescriptor.getSince();
317 if (StringUtils.isNotEmpty(value)) {
318 addedUl = addUl(w, addedUl);
319 w.startElement("li");
320 w.writeMarkup(format("pluginxdoc.mojodescriptor.since", value));
321 w.endElement();
322 }
323
324 value = mojoDescriptor.getPhase();
325 if (StringUtils.isNotEmpty(value)) {
326 addedUl = addUl(w, addedUl);
327 w.startElement("li");
328 w.writeMarkup(format("pluginxdoc.mojodescriptor.phase", value));
329 w.endElement();
330 }
331
332 value = mojoDescriptor.getExecutePhase();
333 if (StringUtils.isNotEmpty(value)) {
334 addedUl = addUl(w, addedUl);
335 w.startElement("li");
336 w.writeMarkup(format("pluginxdoc.mojodescriptor.executePhase", value));
337 w.endElement();
338 }
339
340 value = mojoDescriptor.getExecuteGoal();
341 if (StringUtils.isNotEmpty(value)) {
342 addedUl = addUl(w, addedUl);
343 w.startElement("li");
344 w.writeMarkup(format("pluginxdoc.mojodescriptor.executeGoal", value));
345 w.endElement();
346 }
347
348 value = mojoDescriptor.getExecuteLifecycle();
349 if (StringUtils.isNotEmpty(value)) {
350 addedUl = addUl(w, addedUl);
351 w.startElement("li");
352 w.writeMarkup(format("pluginxdoc.mojodescriptor.executeLifecycle", value));
353 w.endElement();
354 }
355
356 if (mojoDescriptor.isOnlineRequired()) {
357 addedUl = addUl(w, addedUl);
358 w.startElement("li");
359 w.writeMarkup(getString("pluginxdoc.mojodescriptor.onlineRequired"));
360 w.endElement();
361 }
362
363 if (!mojoDescriptor.isInheritedByDefault()) {
364 addedUl = addUl(w, addedUl);
365 w.startElement("li");
366 w.writeMarkup(getString("pluginxdoc.mojodescriptor.inheritedByDefault"));
367 w.endElement();
368 }
369
370 if (addedUl) {
371 w.endElement();
372 }
373 }
374
375
376
377
378
379 private void writeGoalParameterTable(MojoDescriptor mojoDescriptor, XMLWriter w) {
380 List<Parameter> parameterList = mojoDescriptor.getParameters();
381
382
383 List<Parameter> list = filterParameters(parameterList);
384
385 if (!list.isEmpty()) {
386 writeParameterSummary(list, w, mojoDescriptor.getGoal());
387 writeParameterDetails(list, w, mojoDescriptor.getGoal());
388 } else {
389 w.startElement("subsection");
390 w.addAttribute("name", getString("pluginxdoc.mojodescriptor.parameters"));
391
392 w.startElement("p");
393 w.writeMarkup(getString("pluginxdoc.mojodescriptor.noParameter"));
394 w.endElement();
395
396 w.endElement();
397 }
398 }
399
400
401
402
403
404
405
406 private List<Parameter> filterParameters(List<Parameter> parameterList) {
407 List<Parameter> filtered = new ArrayList<>();
408
409 if (parameterList != null) {
410 for (Parameter parameter : parameterList) {
411 if (parameter.isEditable()) {
412 String expression = parameter.getExpression();
413
414 if (expression == null || !expression.startsWith("${component.")) {
415 filtered.add(parameter);
416 }
417 }
418 }
419 }
420
421 return filtered;
422 }
423
424
425
426
427
428 private void writeParameterDetails(List<Parameter> parameterList, XMLWriter w, String goal) {
429 w.startElement("subsection");
430 w.addAttribute("name", getString("pluginxdoc.mojodescriptor.parameter.details"));
431
432 for (Iterator<Parameter> parameters = parameterList.iterator(); parameters.hasNext(); ) {
433 Parameter parameter = parameters.next();
434
435 w.startElement("h4");
436 w.writeMarkup(format("pluginxdoc.mojodescriptor.parameter.name_internal", parameter.getName()));
437 w.endElement();
438
439 String context = "Parameter " + parameter.getName() + " in goal " + goal;
440 if (StringUtils.isNotEmpty(parameter.getDeprecated())) {
441 w.startElement("div");
442 String deprecated = getXhtmlWithValidatedLinks(parameter.getDeprecated(), context);
443 w.writeMarkup(format("pluginxdoc.mojodescriptor.parameter.deprecated", deprecated));
444 w.endElement();
445 }
446
447 w.startElement("div");
448 if (StringUtils.isNotEmpty(parameter.getDescription())) {
449
450 w.writeMarkup(getXhtmlWithValidatedLinks(parameter.getDescription(), context));
451 } else {
452 w.writeMarkup(getString("pluginxdoc.nodescription"));
453 }
454 w.endElement();
455
456 boolean addedUl = false;
457 addedUl = addUl(w, addedUl, parameter.getType());
458 String typeValue = getLinkedType(parameter, false);
459 writeDetail(getString("pluginxdoc.mojodescriptor.parameter.type"), typeValue, w);
460
461 if (StringUtils.isNotEmpty(parameter.getSince())) {
462 addedUl = addUl(w, addedUl);
463 writeDetail(getString("pluginxdoc.mojodescriptor.parameter.since"), parameter.getSince(), w);
464 }
465
466 if (parameter.isRequired()) {
467 addedUl = addUl(w, addedUl);
468 writeDetail(getString("pluginxdoc.mojodescriptor.parameter.required"), getString("pluginxdoc.yes"), w);
469 } else {
470 addedUl = addUl(w, addedUl);
471 writeDetail(getString("pluginxdoc.mojodescriptor.parameter.required"), getString("pluginxdoc.no"), w);
472 }
473
474 String expression = parameter.getExpression();
475 addedUl = addUl(w, addedUl, expression);
476 String property = getPropertyFromExpression(expression);
477 if (property == null) {
478 writeDetail(getString("pluginxdoc.mojodescriptor.parameter.expression"), expression, w);
479 } else {
480 writeDetail(getString("pluginxdoc.mojodescriptor.parameter.property"), property, w);
481 }
482
483 addedUl = addUl(w, addedUl, parameter.getDefaultValue());
484 writeDetail(
485 getString("pluginxdoc.mojodescriptor.parameter.default"),
486 escapeXml(parameter.getDefaultValue()),
487 w);
488
489 addedUl = addUl(w, addedUl, parameter.getAlias());
490 writeDetail(getString("pluginxdoc.mojodescriptor.parameter.alias"), escapeXml(parameter.getAlias()), w);
491
492 if (addedUl) {
493 w.endElement();
494 }
495
496 if (parameters.hasNext()) {
497 w.writeMarkup("<hr/>");
498 }
499 }
500
501 w.endElement();
502 }
503
504 static String getShortType(String type) {
505
506 int startTypeArguments = type.indexOf('<');
507 if (startTypeArguments == -1) {
508 return getShortTypeOfSimpleType(type);
509 } else {
510 StringBuilder shortType = new StringBuilder();
511 shortType.append(getShortTypeOfSimpleType(type.substring(0, startTypeArguments)));
512 shortType
513 .append("<")
514 .append(getShortTypeOfTypeArgument(type.substring(startTypeArguments + 1, type.lastIndexOf(">"))))
515 .append(">");
516 return shortType.toString();
517 }
518 }
519
520 private static String getShortTypeOfTypeArgument(String type) {
521 String[] typeArguments = type.split(",\\s*");
522 StringBuilder shortType = new StringBuilder();
523 for (int i = 0; i < typeArguments.length; i++) {
524 String typeArgument = typeArguments[i];
525 if (typeArgument.contains("<")) {
526
527 return "...";
528 } else {
529 shortType.append(getShortTypeOfSimpleType(typeArgument));
530 if (i < typeArguments.length - 1) {
531 shortType.append(",");
532 }
533 }
534 }
535 return shortType.toString();
536 }
537
538 private static String getShortTypeOfSimpleType(String type) {
539 int index = type.lastIndexOf('.');
540 return type.substring(index + 1);
541 }
542
543 private String getLinkedType(Parameter parameter, boolean isShortType) {
544 final String typeValue;
545 if (isShortType) {
546 typeValue = getShortType(parameter.getType());
547 } else {
548 typeValue = parameter.getType();
549 }
550 if (parameter instanceof EnhancedParameterWrapper) {
551 EnhancedParameterWrapper enhancedParameter = (EnhancedParameterWrapper) parameter;
552 if (enhancedParameter.getTypeJavadocUrl() != null) {
553 URI javadocUrl = enhancedParameter.getTypeJavadocUrl();
554
555 if (javadocUrl.isAbsolute()
556 || disableInternalJavadocLinkValidation
557 || JavadocLinkGenerator.isLinkValid(javadocUrl, reportOutputDirectory.toPath())) {
558 return format(
559 "pluginxdoc.mojodescriptor.parameter.type_link",
560 new Object[] {escapeXml(typeValue), enhancedParameter.getTypeJavadocUrl()});
561 }
562 }
563 }
564 return escapeXml(typeValue);
565 }
566
567 private boolean addUl(XMLWriter w, boolean addedUl, String content) {
568 if (StringUtils.isNotEmpty(content)) {
569 return addUl(w, addedUl);
570 }
571 return addedUl;
572 }
573
574 private boolean addUl(XMLWriter w, boolean addedUl) {
575 if (!addedUl) {
576 w.startElement("ul");
577 addedUl = true;
578 }
579 return addedUl;
580 }
581
582 private String getPropertyFromExpression(String expression) {
583 if (StringUtils.isNotEmpty(expression)
584 && expression.startsWith("${")
585 && expression.endsWith("}")
586 && !expression.substring(2).contains("${")) {
587
588 return expression.substring(2, expression.length() - 1);
589 }
590
591 return null;
592 }
593
594
595
596
597
598
599 private void writeDetail(String param, String value, XMLWriter w) {
600 if (StringUtils.isNotEmpty(value)) {
601 w.startElement("li");
602 w.writeMarkup(format("pluginxdoc.detail", new String[] {param, value}));
603 w.endElement();
604 }
605 }
606
607
608
609
610
611 private void writeParameterSummary(List<Parameter> parameterList, XMLWriter w, String goal) {
612 List<Parameter> requiredParams = getParametersByRequired(true, parameterList);
613 if (!requiredParams.isEmpty()) {
614 writeParameterList(getString("pluginxdoc.mojodescriptor.requiredParameters"), requiredParams, w, goal);
615 }
616
617 List<Parameter> optionalParams = getParametersByRequired(false, parameterList);
618 if (!optionalParams.isEmpty()) {
619 writeParameterList(getString("pluginxdoc.mojodescriptor.optionalParameters"), optionalParams, w, goal);
620 }
621 }
622
623
624
625
626
627
628 private void writeParameterList(String title, List<Parameter> parameterList, XMLWriter w, String goal) {
629 w.startElement("subsection");
630 w.addAttribute("name", title);
631
632 w.startElement("table");
633 w.addAttribute("border", "0");
634
635 w.startElement("tr");
636 w.startElement("th");
637 w.writeText(getString("pluginxdoc.mojodescriptor.parameter.name"));
638 w.endElement();
639 w.startElement("th");
640 w.writeText(getString("pluginxdoc.mojodescriptor.parameter.type"));
641 w.endElement();
642 w.startElement("th");
643 w.writeText(getString("pluginxdoc.mojodescriptor.parameter.since"));
644 w.endElement();
645 w.startElement("th");
646 w.writeText(getString("pluginxdoc.mojodescriptor.parameter.description"));
647 w.endElement();
648 w.endElement();
649
650 for (Parameter parameter : parameterList) {
651 w.startElement("tr");
652
653
654 w.startElement("td");
655 w.writeMarkup(format("pluginxdoc.mojodescriptor.parameter.name_link", parameter.getName()));
656 w.endElement();
657
658
659 w.startElement("td");
660 w.writeMarkup("<code>" + getLinkedType(parameter, true) + "</code>");
661 w.endElement();
662
663
664 w.startElement("td");
665 if (StringUtils.isNotEmpty(parameter.getSince())) {
666 w.writeMarkup("<code>" + parameter.getSince() + "</code>");
667 } else {
668 w.writeMarkup("<code>-</code>");
669 }
670 w.endElement();
671
672
673 w.startElement("td");
674 String description;
675 String context = "Parameter " + parameter.getName() + " in goal " + goal;
676 if (StringUtils.isNotEmpty(parameter.getDeprecated())) {
677 String deprecated = getXhtmlWithValidatedLinks(parameter.getDescription(), context);
678 description = format("pluginxdoc.mojodescriptor.parameter.deprecated", deprecated);
679 } else if (StringUtils.isNotEmpty(parameter.getDescription())) {
680 description = getXhtmlWithValidatedLinks(parameter.getDescription(), context);
681 } else {
682 description = getString("pluginxdoc.nodescription");
683 }
684 w.writeMarkup(description + "<br/>");
685
686 if (StringUtils.isNotEmpty(parameter.getDefaultValue())) {
687 w.writeMarkup(format(
688 "pluginxdoc.mojodescriptor.parameter.defaultValue", escapeXml(parameter.getDefaultValue())));
689 w.writeMarkup("<br/>");
690 }
691
692 String property = getPropertyFromExpression(parameter.getExpression());
693 if (property != null) {
694 w.writeMarkup(format("pluginxdoc.mojodescriptor.parameter.property.description", property));
695 w.writeMarkup("<br/>");
696 }
697
698 if (StringUtils.isNotEmpty(parameter.getAlias())) {
699 w.writeMarkup(format(
700 "pluginxdoc.mojodescriptor.parameter.alias.description", escapeXml(parameter.getAlias())));
701 }
702
703 w.endElement();
704 w.endElement();
705 }
706
707 w.endElement();
708 w.endElement();
709 }
710
711
712
713
714
715
716 private List<Parameter> getParametersByRequired(boolean required, List<Parameter> parameterList) {
717 List<Parameter> list = new ArrayList<>();
718
719 for (Parameter parameter : parameterList) {
720 if (parameter.isRequired() == required) {
721 list.add(parameter);
722 }
723 }
724
725 return list;
726 }
727
728
729
730
731
732
733 private ResourceBundle getBundle() {
734 return ResourceBundle.getBundle("pluginxdoc", locale, getClass().getClassLoader());
735 }
736
737
738
739
740
741
742 private String getString(String key) {
743 return getBundle().getString(key);
744 }
745
746
747
748
749
750
751
752
753
754 private String format(String key, Object arg1) {
755 return format(key, new Object[] {arg1});
756 }
757
758
759
760
761
762
763
764
765
766 private String format(String key, Object[] args) {
767 String pattern = getString(key);
768
769 pattern = StringUtils.replace(pattern, "'", "''");
770
771 MessageFormat messageFormat = new MessageFormat("");
772 messageFormat.setLocale(locale);
773 messageFormat.applyPattern(pattern);
774
775 return messageFormat.format(args);
776 }
777
778
779
780
781
782 private String escapeXml(String text) {
783 if (text != null) {
784 text = text.replace("&", "&");
785 text = text.replace("<", "<");
786 text = text.replace(">", ">");
787 text = text.replace("\"", """);
788 text = text.replace("\'", "'");
789 }
790 return text;
791 }
792
793 String getXhtmlWithValidatedLinks(String xhtmlText, String context) {
794 if (disableInternalJavadocLinkValidation) {
795 return xhtmlText;
796 }
797 StringBuffer sanitizedXhtmlText = new StringBuffer();
798
799 Matcher matcher = HTML_LINK_PATTERN.matcher(xhtmlText);
800 while (matcher.find()) {
801 URI link;
802 try {
803 link = new URI(matcher.group(1));
804 if (!link.isAbsolute() && !JavadocLinkGenerator.isLinkValid(link, reportOutputDirectory.toPath())) {
805 matcher.appendReplacement(sanitizedXhtmlText, matcher.group(2));
806 LOG.debug("Removed invalid link {} in {}", link, context);
807 } else {
808 matcher.appendReplacement(sanitizedXhtmlText, matcher.group(0));
809 }
810 } catch (URISyntaxException e) {
811 LOG.warn("Invalid URI {} found in {}. Cannot validate, leave untouched", matcher.group(1), context);
812 matcher.appendReplacement(sanitizedXhtmlText, matcher.group(0));
813 }
814 }
815 matcher.appendTail(sanitizedXhtmlText);
816 return sanitizedXhtmlText.toString();
817 }
818 }