View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2012-2015 ForgeRock AS.
15   * Partial Copyright 2022 Wren Security
16   */
17  package org.forgerock.doc.maven;
18  
19  import static org.twdata.maven.mojoexecutor.MojoExecutor.element;
20  import static org.twdata.maven.mojoexecutor.MojoExecutor.name;
21  
22  import org.apache.commons.io.FilenameUtils;
23  import org.apache.maven.execution.MavenSession;
24  import org.apache.maven.plugin.AbstractMojo;
25  import org.apache.maven.plugin.BuildPluginManager;
26  import org.apache.maven.plugin.MojoExecutionException;
27  import org.apache.maven.plugins.annotations.Component;
28  import org.apache.maven.plugins.annotations.Parameter;
29  import org.apache.maven.project.MavenProject;
30  import org.forgerock.doc.maven.backstage.ArtifactItem;
31  import org.forgerock.doc.maven.utils.NameUtils;
32  import org.twdata.maven.mojoexecutor.MojoExecutor;
33  
34  import java.io.File;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.text.SimpleDateFormat;
38  import java.util.ArrayList;
39  import java.util.Date;
40  import java.util.HashMap;
41  import java.util.LinkedList;
42  import java.util.List;
43  import java.util.Map;
44  import java.util.Properties;
45  import java.util.Set;
46  
47  /**
48   * AbstractMojo implementation for building core documentation from <a
49   * href="http://www.docbook.org/tdg51/en/html/docbook.html">DocBook XML</a>
50   * using <a href="http://code.google.com/p/docbkx-tools/">docbkx-tools</a>.
51   */
52  abstract public class AbstractDocbkxMojo extends AbstractMojo {
53  
54      /**
55       * Versions of plugins driven by this plugin.
56       */
57      private Properties versions;
58  
59      /**
60       * Load versions of plugins driven by this plugin.
61       */
62      private void loadVersions() {
63          versions = new Properties();
64          InputStream inputStream = null;
65  
66          try {
67              inputStream = getClass().getResourceAsStream("/versions.properties");
68              if (inputStream == null) {
69                  throw new IOException("Could not read properties resource");
70              }
71              versions.load(inputStream);
72          } catch (IOException e) {
73              getLog().error("Failed to read plugin version properties", e);
74          } finally {
75              if (inputStream != null) {
76                  try {
77                      inputStream.close();
78                  } catch (IOException e) {
79                      // Ignore exception.
80                  }
81              }
82          }
83      }
84  
85      /**
86       * Get a version property based on the version properties file.
87       *
88       * <br>
89       *
90       * Prefer the current value if it is already set.
91       *
92       * @param currentValue  If not null or empty, then return this value.
93       * @param key           Otherwise return the value for this key.
94       * @return              The currentValue if set, otherwise the property.
95       */
96      private String getVersionProperty(String currentValue, String key) {
97          if (currentValue != null && !currentValue.isEmpty()) {
98              return currentValue;
99          }
100 
101         if (versions == null) {
102             loadVersions();
103         }
104 
105         return versions.getProperty(key);
106     }
107 
108     /**
109      * Whether to use WinAnsi encoding for embedded fonts.
110      * If {@code true}, then some UTF-8 characters cannot be used.
111      */
112     private String ansi = "false";
113 
114     /**
115      * Whether to use WinAnsi encoding for embedded fonts.
116      *
117      * <br>
118      *
119      * Value: {@code false}
120      *
121      * @return Whether WinAnsi encoded should be used for embedded fonts.
122      */
123     public final String useAnsi() {
124         return ansi;
125     }
126 
127     /**
128      * Should sections have numeric labels?
129      *
130      * <br>
131      *
132      * docbkx-tools element: &lt;sectionAutolabel&gt;
133      */
134     private String areSectionsAutolabeled = "true";
135 
136     /**
137      * Whether sections should have numeric labels.
138      *
139      * <br>
140      *
141      * Value: {@code true}
142      *
143      * <br>
144      *
145      * docbkx-tools element: &lt;sectionAutolabel&gt;
146      *
147      * @return Whether sections should have numeric labels.
148      */
149     public final String areSectionsAutolabeled() {
150         return areSectionsAutolabeled;
151     }
152 
153     /**
154      * Base directory for Asciidoc source files.
155      */
156     @Parameter(defaultValue = "${basedir}/src/main/asciidoc")
157     private File asciidocSourceDirectory;
158 
159     /**
160      * Get the base directory for Asciidoc source files.
161      * These files remain unchanged during processing.
162      *
163      * <br>
164      *
165      * Default: {@code ${basedir}/src/main/asciidoc}.
166      *
167      * @return The base directory for Asciidoc source files.
168      */
169     public File getAsciidocSourceDirectory() {
170         return asciidocSourceDirectory;
171     }
172 
173     /**
174      * Version of the Asciidoctor Maven plugin to use.
175      */
176     @Parameter
177     private String asciidoctorPluginVersion;
178 
179     /**
180      * Returns the version of the Asciidoctor Maven plugin to use.
181      *
182      * @return The version of the Asciidoctor Maven plugin to use.
183      */
184     public String getAsciidoctorPluginVersion() {
185         return getVersionProperty(asciidoctorPluginVersion, "asciidoctorPluginVersion");
186     }
187 
188     /**
189      * File system directory for Backstage layout output
190      * relative to the build directory.
191      */
192     @Parameter(defaultValue = "backstage")
193     private String backstageDirectory;
194 
195     /**
196      * Get the file system directory for Backstage layout output.
197      *
198      * <br>
199      *
200      * Default: {@code ${project.build.directory}/backstage}
201      *
202      * @return The file system directory for Backstage layout output.
203      */
204     public File getBackstageDirectory() {
205         return new File(getBuildDirectory(), backstageDirectory);
206     }
207 
208     /**
209      * Product name as shown on Backstage.
210      */
211     @Parameter(property = "backstageProductName")
212     private String backstageProductName;
213 
214     /**
215      * Get the product name as shown on Backstage.
216      *
217      * <br>
218      *
219      * Default: {@code projectName}
220      *
221      * @return The product name as shown on Backstage.
222      */
223     public String getBackstageProductName() {
224         return backstageProductName != null ? backstageProductName : projectName;
225     }
226 
227     /**
228      * Get the base configuration applicable to all builds with the docbkx-tools plugin.
229      *
230      * @return The configuration applicable to all builds.
231      */
232     public ArrayList<MojoExecutor.Element> getBaseConfiguration() {
233         ArrayList<MojoExecutor.Element> cfg = new ArrayList<>();
234 
235         cfg.add(element(name("draftMode"), isDraftMode()));
236         cfg.add(element(name("draftWatermarkImage"), getDraftWatermarkURL()));
237         cfg.add(element(name("highlightSource"), useSyntaxHighlighting()));
238         cfg.add(element(name("sectionAutolabel"), areSectionsAutolabeled()));
239         cfg.add(element(name("sectionLabelIncludesComponentLabel"),
240                 doesSectionLabelIncludeComponentLabel()));
241         cfg.add(element(name("xincludeSupported"), isXincludeSupported()));
242         cfg.add(element(name("sourceDirectory"), path(getDocbkxModifiableSourcesDirectory())));
243 
244         return cfg;
245     }
246 
247     /**
248      * Project base directory, needed to workaround bugs with *target.db and webhelp.
249      */
250     @Parameter(defaultValue = "${basedir}")
251     private File baseDir;
252 
253     /**
254      * Project base directory, needed to workaround bugs with *target.db and webhelp.
255      *
256      * <br>
257      *
258      * Default: {@code ${basedir}}
259      *
260      * @return The project base directory.
261      */
262     public File getBaseDir() {
263         return baseDir;
264     }
265 
266     /**
267      * The artifactId of the branding to use.
268      */
269     @Parameter(defaultValue = "doc-default-branding")
270     private String brandingArtifactId;
271 
272     /**
273      * Gets the branding artifactId to use.
274      *
275      * <br>
276      *
277      * Default: {@code doc-default-branding}.
278      *
279      * @return The branding artifactId.
280      */
281     public String getBrandingArtifactId() {
282         return brandingArtifactId;
283     }
284 
285     /**
286      * The groupId of the branding to use.
287      */
288     @Parameter(defaultValue = "org.wrensecurity.commons")
289     private String brandingGroupId;
290 
291     /**
292      * Gets the groupId of the branding artifact to use.
293      *
294      * <br>
295      *
296      * Default: {@code org.wrensecurity.common}
297      *
298      * @return The branding groupId.
299      */
300     public String getBrandingGroupId() {
301         return brandingGroupId;
302     }
303 
304     /**
305      * Version of the branding artifact to use.
306      */
307     @Parameter
308     private String brandingVersion;
309 
310     /**
311      * Gets the version of the branding artifact to use.
312      *
313      * @return The branding artifact version.
314      */
315     public String getBrandingVersion() {
316         return getVersionProperty(brandingVersion, "brandingVersion");
317     }
318 
319     /**
320      * The project build directory.
321      *
322      * <br>
323      *
324      * Default: {@code ${project.build.directory}}.
325      */
326     @Parameter(defaultValue = "${project.build.directory}")
327     private File buildDirectory;
328 
329     /**
330      * Get the project build directory for this plugin.
331      *
332      * <br>
333      *
334      * Default: {@code ${project.build.directory}}.
335      *
336      * @return The build directory.
337      */
338     public File getBuildDirectory() {
339         return buildDirectory;
340     }
341 
342     /**
343      * Whether to build a .zip of the release content.
344      */
345     @Parameter(defaultValue = "false", property = "buildReleaseZip")
346     private boolean buildReleaseZip;
347 
348     /**
349      * Whether to build a .zip containing the release content.
350      *
351      * <br>
352      *
353      * Default: {@code false}
354      *
355      * @return true if the .zip should be built.
356      */
357     public final boolean doBuildReleaseZip() {
358         return buildReleaseZip;
359     }
360 
361     /**
362      * Location of the chunked HTML XSL stylesheet customization file,
363      * relative to the build directory.
364      *
365      * <br>
366      *
367      * docbkx-tools element: &lt;htmlCustomization&gt;
368      */
369     private String chunkedHTMLCustomization = "docbkx-stylesheets/html/chunked.xsl";
370 
371     /**
372      * Get the location of the chunked HTML XSL stylesheet customization file.
373      *
374      * <br>
375      *
376      * Default: {@code ${project.build.directory}/docbkx-stylesheets/html/chunked.xsl}
377      *
378      * <br>
379      *
380      * docbkx-tools element: &lt;htmlCustomization&gt;
381      *
382      * @return The location of the chunked HTML XSL stylesheet.
383      */
384     public final File getChunkedHTMLCustomization() {
385         return new File(getBuildDirectory(), chunkedHTMLCustomization);
386     }
387 
388     /**
389      * The {@code artifactId} of the common content artifact.
390      */
391     @Parameter(defaultValue = "doc-common-content")
392     private String commonContentArtifactId;
393 
394     /**
395      * Get the {@code artifactId} of the common content artifact.
396      *
397      * <br>
398      *
399      * Default: {@code doc-common-content}.
400      *
401      * @return The {@code artifactId} of the common content artifact.
402      */
403     public String getCommonContentArtifactId() {
404         return commonContentArtifactId;
405     }
406 
407     /**
408      * The {@code groupId} of the common content artifact.
409      */
410     @Parameter(defaultValue = "org.wrensecurity.commons")
411     private String commonContentGroupId;
412 
413     /**
414      * Get the {@code groupId} of the common content artifact.
415      *
416      * <br>
417      *
418      * Default: {@code org.wrensecurity.common}.
419      *
420      * @return The {@code groupId} of the common content artifact.
421      */
422     public String getCommonContentGroupId() {
423         return commonContentGroupId;
424     }
425 
426     /**
427      * Version of the common content artifact to use.
428      */
429     @Parameter
430     private String commonContentVersion;
431 
432     /**
433      * Get the version of the common content artifact to use.
434      *
435      * @return the version of the common content artifact to use.
436      */
437     public String getCommonContentVersion() {
438         return getVersionProperty(commonContentVersion, "commonContentVersion");
439     }
440 
441     /**
442      * Whether to copy resource files alongside docs for site, release.
443      */
444     @Parameter(defaultValue = "false")
445     private boolean copyResourceFiles;
446 
447     /**
448      * Whether to copy resource files alongside docs for site, release.
449      *
450      * <br>
451      *
452      * Default: false
453      *
454      * @return true if resource files should be copied.
455      */
456     public boolean doCopyResourceFiles() {
457         return copyResourceFiles;
458     }
459 
460     /**
461      * Whether to build artifacts from pre-processed sources.
462      */
463     @Parameter(defaultValue = "true")
464     private boolean createArtifacts;
465 
466     /**
467      * Whether to build artifacts from pre-processed sources.
468      *
469      * <br>
470      *
471      * Default: true
472      *
473      * @return true if artifacts should be build from pre-processed sources.
474      */
475     public boolean doCreateArtifacts() {
476         return createArtifacts;
477     }
478 
479     /**
480      * Doc artifacts to unpack when preparing Backstage layout.
481      */
482     @Parameter
483     private List<ArtifactItem> artifactItems;
484 
485     /**
486      * Get the doc artifacts to unpack when preparing Backstage layout.
487      *
488      * @return The doc artifacts to unpack when preparing Backstage layout.
489      */
490     public List<ArtifactItem> getArtifactItems() {
491         return artifactItems != null ? artifactItems : new LinkedList<ArtifactItem>();
492     }
493 
494     /**
495      * Base directory for the modifiable copy of DocBook XML source files,
496      * relative to the build directory.
497      */
498     private String docbkxModifiableSourcesDirectory = "docbkx-sources";
499 
500     /**
501      * Get the base directory for the modifiable copy of DocBook XML source files.
502      * This copy is modified during preparation for processing.
503      *
504      * <br>
505      *
506      * Value: {@code ${project.build.directory}/docbkx-sources}
507      *
508      * @return The base directory for the modifiable copy of DocBook XML source files.
509      */
510     public File getDocbkxModifiableSourcesDirectory() {
511         return new File(getBuildDirectory(), docbkxModifiableSourcesDirectory);
512     }
513 
514     /**
515      * Base directory for built documentation, relative to the build directory.
516      */
517     private String docbkxOutputDirectory = "docbkx";
518 
519     /**
520      * Base directory for built documentation.
521      *
522      * <br>
523      *
524      * Value: {@code ${project.build.directory}/docbkx}
525      *
526      * @return The base directory for built documentation.
527      */
528     public File getDocbkxOutputDirectory() {
529         return new File(buildDirectory, docbkxOutputDirectory);
530     }
531 
532     /**
533      * Base directory for DocBook XML source files.
534      */
535     @Parameter(defaultValue = "${basedir}/src/main/docbkx", property = "docbkxSourceDirectory")
536     private File docbkxSourceDirectory;
537 
538     /**
539      * Get the base directory for DocBook XML source files.
540      * These files remain unchanged during processing.
541      *
542      * <br>
543      *
544      * Default: {@code ${basedir}/src/main/docbkx}.
545      *
546      * @return The base directory for DocBook XML source files.
547      */
548     public File getDocbkxSourceDirectory() {
549         return docbkxSourceDirectory;
550     }
551 
552     /**
553      * Docbkx Tools plugin version to use.
554      */
555     @Parameter
556     private String docbkxVersion;
557 
558     /**
559      * Get the docbkx-tools plugin version to use.
560      *
561      * @return The docbkx-tools plugin version to use
562      */
563     public String getDocbkxVersion() {
564         return getVersionProperty(docbkxVersion, "docbkxVersion");
565     }
566 
567     /**
568      * Supported DocBook profile attributes.
569      */
570     public enum ProfileAttributes {
571         /** Computer or chip architecture, such as i386. */
572         arch,
573 
574         /** Intended audience of the content, such as instructor. Added in DocBook version 5.0. */
575         audience,
576 
577         /** General purpose conditional attribute, with no preassigned semantics. */
578         condition,
579 
580         /** Standards conformance, such as lsb (Linux Standards Base). */
581         conformance,
582 
583         /** Language code, such as de_DE. */
584         lang,
585 
586         /** Operating system. */
587         os,
588 
589         /** Editorial revision, such as v2.1. */
590         revision,
591 
592         /** Revision status of the element, such as changed. This attribute has a fixed set of values to choose from. */
593         revisionflag,
594 
595         /** General purpose attribute, with no preassigned semantics. Use with caution for profiling. */
596         role,
597 
598         /** Security level, such as high. */
599         security,
600 
601         /** Editorial or publication status, such as InDevelopment or draft. */
602         status,
603 
604         /** Level of user experience, such as beginner. */
605         userlevel,
606 
607         /** Product vendor, such as apache. */
608         vendor,
609 
610         /** Word size (width in bits) of the computer architecture, such as 64bit. Added in DocBook version 4.4. */
611         wordsize
612     }
613 
614     /**
615      * Returns true if the attribute is one of the expected ProfileAttributes.
616      * @param attribute     The attribute to check.
617      * @return true if the attribute is one of the expected ProfileAttributes.
618      */
619     private boolean isProfileAttribute(final String attribute) {
620         try {
621             ProfileAttributes.valueOf(attribute);
622             return true;
623         } catch (IllegalArgumentException e) {
624             return false;
625         }
626     }
627 
628     /**
629      * Include elements with these
630      * <a href="http://www.sagehill.net/docbookxsl/Profiling.html">DocBook profile</a> settings.
631      * <br>
632      * See <a href="http://www.sagehill.net/docbookxsl/Profiling.html#ProfilingAttribs"
633      * >the list of profile attributes specified for DocBook</a>.
634      * <br>
635      * Separate multiple attribute values for the same attribute with spaces.
636      * <br>
637      * For example, to include all elements with {@code os="linux"} or {@code os="unix"}
638      * and all elements with no {@code os} attribute,
639      * use the following configuration:
640      * <pre>
641      * &lt;inclusions>
642      *  &lt;os>linux unix&lt;/os>
643      * &lt;/inclusions>
644      * </pre>
645      */
646     @Parameter
647     private Map<String, String> inclusions;
648 
649     /**
650      * Returns a map of DocBook profile settings to include elements.
651      * <br>
652      * This implementation ignores unexpected profile settings.
653      *
654      * @return A map of DocBook profile settings to include elements,
655      *         or null if none are set.
656      */
657     public Map<String, String> getInclusions() {
658         if (inclusions == null) {
659             return null;
660         }
661 
662         Map<String, String> result = new HashMap<>();
663         for (String attribute : inclusions.keySet()) {
664             if (isProfileAttribute(attribute)) {
665                 result.put(attribute, inclusions.get(attribute));
666             }
667         }
668         return result;
669     }
670 
671     /**
672      * Exclude elements with these
673      * <a href="http://www.sagehill.net/docbookxsl/Profiling.html">DocBook profile</a> settings.
674      * <br>
675      * See <a href="http://www.sagehill.net/docbookxsl/Profiling.html#ProfilingAttribs"
676      * >the list of profile attributes specified for DocBook</a>.
677      * <br>
678      * Separate multiple attribute values for the same attribute with spaces.
679      * <br>
680      * For example, to exclude all elements with {@code os="linux"} and {@code os="unix"},
681      * use the following configuration:
682      * <pre>
683      * &lt;exclusions>
684      *  &lt;os>linux unix&lt;/os>
685      * &lt;/exclusions>
686      * </pre>
687      */
688     @Parameter
689     private Map<String, String> exclusions;
690 
691     /**
692      * Returns a map of DocBook profile settings to exclude elements.
693      * <br>
694      * This implementation ignores unexpected profile settings.
695      *
696      * @return A map of DocBook profile settings to exclude elements,
697      *         or null if none are set.
698      */
699     public Map<String, String> getExclusions() {
700         if (exclusions == null) {
701             return null;
702         }
703 
704         Map<String, String> result = new HashMap<>();
705         for (String attribute : exclusions.keySet()) {
706             if (isProfileAttribute(attribute)) {
707                 result.put(attribute, exclusions.get(attribute));
708             }
709         }
710         return result;
711     }
712 
713     /**
714      * Get document names for the current project.
715      *
716      * @return The document names for the current project.
717      * @throws MojoExecutionException No document names found.
718      */
719     public Set<String> getDocNames() throws MojoExecutionException {
720 
721         Set<String> docNames = NameUtils.getDocumentNames(
722                 getDocbkxModifiableSourcesDirectory(), getDocumentSrcName());
723 
724         if (docNames.isEmpty()) {
725             throw new MojoExecutionException("No document names found.");
726         }
727         return docNames;
728     }
729 
730     /**
731      * URL to site for published documentation.
732      */
733     @Parameter(defaultValue = "https://docs.wrensecurity.org/")
734     private String docsSite;
735 
736     /**
737      * Get the URL to the site for published documentation.
738      *
739      * <br>
740      *
741      * Default: {@code https://docs.wrensecurity.org/}
742      *
743      * @return The URL to the site for published documentation.
744      */
745     public String getDocsSite() {
746         return docsSite;
747     }
748 
749     /**
750      * Top-level DocBook XML source document name.
751      */
752     @Parameter(defaultValue = "index.xml", property = "documentSrcName")
753     private String documentSrcName;
754 
755     /**
756      * Get the top-level DocBook XML source document name.
757      *
758      * <br>
759      *
760      * Default: {@code index.xml}.
761      *
762      * <br>
763      *
764      * Documents included in the documentation set
765      * such as books, articles, and references share a common entry point,
766      * which is a file having the name specified by this element.
767      *
768      * <br>
769      *
770      * For example, if your documentation set has
771      * Release Notes, an Installation Guide, an Admin Guide, a Dev Guide, and a Reference,
772      * your source layout under the base DocBook XML source directory
773      * might look like the following:
774      *
775      * <pre>
776      * src/main/docbkx/
777      *  admin-guide/
778      *   index.xml
779      *   ...other files...
780      *  dev-guide/
781      *   index.xml
782      *   ...other files...
783      *  install-guide/
784      *   index.xml
785      *   ...other files...
786      *  reference/
787      *   index.xml
788      *   ...other files...
789      *  release-notes/
790      *   index.xml
791      *   ...other files...
792      *  shared/
793      *   ...other files...
794      * </pre>
795      *
796      * <br>
797      *
798      * The {@code ...other files...} can have whatever names you want,
799      * as long as the name does not match the file name you configure.
800      * For example, if you were to hand-code an index file
801      * you could name it {@code ix.xml}.
802      *
803      * @return File name of top-level DocBook XML source document.
804      */
805     public String getDocumentSrcName() {
806         return documentSrcName;
807     }
808 
809     /**
810      * Whether section labels should include parent numbers,
811      * like 1.1, 1.2, 1.2.1, 1.2.2.
812      *
813      * <br>
814      *
815      * docbkx-tools element: &lt;sectionLabelIncludesComponentLabel&gt;
816      */
817     private String doesSectionLabelIncludeComponentLabel = "true";
818 
819     /**
820      * Whether section labels should include parent numbers,
821      * like 1.1, 1.2, 1.2.1, 1.2.2.
822      *
823      * <br>
824      *
825      * Value: {@code true}
826      *
827      * <br>
828      *
829      * docbkx-tools element: &lt;sectionLabelIncludesComponentLabel&gt;
830      *
831      * @return Whether section labels should include parent numbers.
832      */
833     public final String doesSectionLabelIncludeComponentLabel() {
834         return doesSectionLabelIncludeComponentLabel;
835     }
836 
837     /**
838      * For draft mode, URL to the background watermark image.
839      *
840      * <br>
841      *
842      * docbkx-tools element: &lt;draftWatermarkImage&gt;
843      */
844     @Parameter(defaultValue = "http://docbook.sourceforge.net/release/images/draft.png")
845     private String draftWatermarkURL;
846 
847     /**
848      * For draft mode, URL to the background watermark image.
849      *
850      * <br>
851      *
852      * Default: {@code http://docbook.sourceforge.net/release/images/draft.png}
853      *
854      * <br>
855      *
856      * docbkx-tools element: &lt;draftWatermarkImage&gt;
857      *
858      * @return The URL to the background watermark image.
859      */
860     public final String getDraftWatermarkURL() {
861         return draftWatermarkURL;
862     }
863 
864     /**
865      * URL to JSON object showing EOSL versions for each project.
866      */
867     @Parameter(defaultValue = "http://docs.wrensecurity.org/eosl.json")
868     private String eoslJson;
869 
870     /**
871      * Get the URL to JSON object showing EOSL versions for each project.
872      *
873      * @return The URL to the JSON object.
874      */
875     public String getEoslJson() {
876         return eoslJson;
877     }
878 
879     /**
880      * Location of the EPUB XSL stylesheet customization file,
881      * relative to the build directory.
882      *
883      * <br>
884      *
885      * docbkx-tools element: &lt;epubCustomization&gt;
886      */
887     private String epubCustomization = "docbkx-stylesheets/epub/coredoc.xsl";
888 
889     /**
890      * Get the location of the EPUB XSL stylesheet customization file.
891      *
892      * <br>
893      *
894      * Default: {@code ${project.build.directory}/docbkx-stylesheets/epub/coredoc.xsl}
895      *
896      * <br>
897      *
898      * docbkx-tools element: &lt;epubCustomization&gt;
899      *
900      * @return The location of the EPUB XSL stylesheet customization file.
901      */
902     public final File getEpubCustomization() {
903         return new File(getBuildDirectory(), epubCustomization);
904     }
905 
906     /**
907      * Favicon link element for the pre-site version of the HTML.
908      */
909     @Parameter(defaultValue = "<link rel=\"shortcut icon\" href=\"https://wrensecurity.org/favicon.ico\">")
910     private String faviconLink;
911 
912     /**
913      * Get the favicon link element for the pre-site version of the HTML.
914      *
915      * @return The link element.
916      */
917     public final String getFaviconLink() {
918         return faviconLink;
919     }
920 
921     /**
922      * Location of the FO XSL stylesheet customization file (for PDF, RTF),
923      * relative to the build directory.
924      *
925      * <br>
926      *
927      * docbkx-tools element: &lt;foCustomization&gt;
928      */
929     private String foCustomization = "docbkx-stylesheets/fo/coredoc.xsl";
930 
931     /**
932      * Get the location of the FO XSL stylesheet customization file (for PDF, RTF).
933      *
934      * <br>
935      *
936      * Value: {@code ${project.build.directory}/docbkx-stylesheets/fo/coredoc.xsl}
937      *
938      * <br>
939      *
940      * docbkx-tools element: &lt;foCustomization&gt;
941      *
942      * @return The location of the FO XSL stylesheet.
943      */
944     public final File getFoCustomization() {
945         return new File(getBuildDirectory(), foCustomization);
946     }
947 
948     /**
949      * Directory where fonts and font metrics are stored,
950      * relative to the build directory.
951      */
952     private String fontsDirectory  = "fonts";
953 
954     /**
955      * Directory where fonts and font metrics are stored.
956      *
957      * <br>
958      *
959      * Value: {@code ${project.build.directory}/fonts}
960      *
961      * @return The directory where fonts and font metrics are stored.
962      */
963     public final File getFontsDirectory() {
964         return new File(getBuildDirectory(), fontsDirectory);
965     }
966 
967     /**
968      * Version of the FOP hyphenation plugin to use.
969      */
970     @Parameter
971     private String fopHyphVersion;
972 
973     /**
974      * Get the version of the FOP hyphenation plugin to use.
975      * @return The version of the FOP hyphenation plugin to use.
976      */
977     public String getFopHyphVersion() {
978         return getVersionProperty(fopHyphVersion, "fopHyphVersion");
979     }
980 
981     /**
982      * Log level when building FO output (PDF, RTF).
983      *
984      * <br>
985      *
986      * docbkx-tools element: &lt;fopLogLevel&gt;
987      */
988     @Parameter(defaultValue = "ERROR")
989     private String fopLogLevel;
990 
991     /**
992      * Log level when building FO output (PDF, RTF).
993      *
994      * <br>
995      *
996      * Default: {@code ERROR}
997      *
998      * <br>
999      *
1000      * docbkx-tools element: &lt;fopLogLevel&gt;
1001      *
1002      * @return The log level for Apache FOP.
1003      */
1004     public final String getFopLogLevel() {
1005         return fopLogLevel;
1006     }
1007 
1008     /**
1009      * Supported output formats.
1010      */
1011     public enum Format {
1012         /**
1013          * EPUB v2 without styling; not ready for publication.
1014          */
1015         epub,
1016 
1017         /**
1018          * Styled single-page and chunked HTML 4.
1019          */
1020         html,
1021 
1022         /**
1023          * Styled with HtmlForBootstrap single-page HTML 4.
1024          */
1025         bootstrap,
1026 
1027         /**
1028          * Reference manual pages for use with the {@code man} command.
1029          */
1030         man,
1031 
1032         /**
1033          * PDF.
1034          */
1035         pdf,
1036 
1037         /**
1038          * RTF without styling; not ready for publication.
1039          */
1040         rtf,
1041 
1042         /**
1043          * Styled DocBook Webhelp format.
1044          */
1045         webhelp,
1046 
1047         /**
1048          * Single-page XHTML5 without styling except syntax highlighting;
1049          * not ready for publication as is.
1050          */
1051         xhtml5
1052     }
1053 
1054     /**
1055      * Comma-separated list of output formats to generate.
1056      */
1057     @Parameter(property = "formats", defaultValue = "bootstrap,pdf")
1058     private List<Format> formats;
1059 
1060     /**
1061      * Return a list of output formats to generate.
1062      *
1063      * <br>
1064      *
1065      * Default: bootstrap,pdf
1066      *
1067      * @return List of output formats.
1068      */
1069     public List<Format> getFormats() {
1070         return this.formats;
1071     }
1072 
1073     /**
1074      * Google Analytics identifier for the project.
1075      *
1076      * <br>
1077      *
1078      * The identifier for docs.forgerock.org is {@code UA-REMOVED-VALUE}.
1079      */
1080     @Parameter(defaultValue = "UA-REMOVED-VALUE")
1081     private String googleAnalyticsId;
1082 
1083     /**
1084      * Google Analytics identifier for the project.
1085      *
1086      * <br>
1087      *
1088      * Default: {@code UA-REMOVED-VALUE}
1089      *
1090      * @return The Google Analytics identifier.
1091      */
1092     public String getGoogleAnalyticsId() {
1093         return googleAnalyticsId;
1094     }
1095 
1096     /**
1097      * Whether these are draft documents, rather than final documents.
1098      *
1099      * <br>
1100      *
1101      * docbkx-tools element: &lt;draftMode&gt;
1102      */
1103     @Parameter(defaultValue = "yes", property = "isDraftMode")
1104     private String isDraftMode;
1105 
1106     /**
1107      * Whether these are draft documents, rather than final documents.
1108      *
1109      * <br>
1110      *
1111      * Default: {@code yes}
1112      *
1113      * <br>
1114      *
1115      * docbkx-tools element: &lt;draftMode&gt;
1116      *
1117      * @return Whether these are draft documents.
1118      */
1119     public final String isDraftMode() {
1120         return isDraftMode;
1121     }
1122 
1123     /**
1124      * Whether documents should be allowed to include other documents.
1125      *
1126      * <br>
1127      *
1128      * docbkx-tools element: &lt;xincludeSupported&gt;
1129      */
1130     private String isXincludeSupported = "true";
1131 
1132     /**
1133      * Whether documents should be allowed to include other documents.
1134      *
1135      * <br>
1136      *
1137      * Value: {@code true}
1138      *
1139      * <br>
1140      *
1141      * docbkx-tools element: &lt;xincludeSupported&gt;
1142      *
1143      * @return Where documents should be allowed to include other documents.
1144      */
1145     public final String isXincludeSupported() {
1146         return isXincludeSupported;
1147     }
1148 
1149     /**
1150      * JavaScript file name, found under {@code /js/} in plugin resources.
1151      */
1152     private String javaScriptFileName = "uses-jquery.js";
1153 
1154     /**
1155      * Get the main JavaScript file name, found under {@code /js/} in plugin resources.
1156      *
1157      * <br>
1158      *
1159      * Value: {@code uses-jquery.js}
1160      *
1161      * @return The JavaScript file name.
1162      */
1163     public String getJavaScriptFileName() {
1164         return javaScriptFileName;
1165     }
1166 
1167     /**
1168      * The set of source paths where cited Java files are found.
1169      */
1170     @Parameter
1171     private List<File> jCiteSourcePaths;
1172 
1173     /**
1174      * Get the source paths where cited Java files are found.
1175      *
1176      * <br>
1177      *
1178      * If source paths are not set, {@code src/main/java} is used.
1179      *
1180      * @return the set of source paths where cited Java files are found.
1181      */
1182     public List<File> getJCiteSourcePaths() {
1183         return jCiteSourcePaths;
1184     }
1185 
1186     /**
1187      * JCite version to use for code citations.
1188      */
1189     @Parameter
1190     private String jCiteVersion;
1191 
1192     /**
1193      * Get the JCite artifact version to use for Java code citations.
1194      *
1195      * @return The JCite artifact version to use for Java code citations.
1196      */
1197     public String getJCiteVersion() {
1198         return getVersionProperty(jCiteVersion, "jCiteVersion");
1199     }
1200 
1201     /**
1202      * Whether to keep a custom index.html file for the documentation set.
1203      */
1204     @Parameter(defaultValue = "false")
1205     private boolean keepCustomIndexHtml;
1206 
1207     /**
1208      * Whether to keep a custom index.html file for the documentation set.
1209      *
1210      * <br>
1211      *
1212      * Default: {@code false}
1213      *
1214      * @return Whether to keep a custom index.html file.
1215      */
1216     public boolean keepCustomIndexHtml() {
1217         return keepCustomIndexHtml;
1218     }
1219 
1220     /**
1221      * URL to JSON object showing latest versions for each project.
1222      */
1223     @Parameter(defaultValue = "http://docs.wrensecurity.org/latest.json")
1224     private String latestJson;
1225 
1226     /**
1227      * Get the URL to JSON object showing latest versions for each project.
1228      *
1229      * @return The URL to the JSON object.
1230      */
1231     public String getLatestJson() {
1232         return latestJson;
1233     }
1234 
1235     /**
1236      * ForgeRock link tester plugin version to use.
1237      */
1238     @Parameter
1239     private String linkTesterVersion;
1240 
1241     /**
1242      * ForgeRock link tester plugin version to use.
1243      *
1244      * @return The link tester plugin version to use.
1245      */
1246     public String getLinkTesterVersion() {
1247         return getVersionProperty(linkTesterVersion, "linkTesterVersion");
1248     }
1249 
1250     /**
1251      * Locale tag for the documentation set.
1252      */
1253     @Parameter(defaultValue = "en")
1254     private String localeTag;
1255 
1256     /**
1257      * Get the Locale tag for the documentation set.
1258      *
1259      * <br>
1260      *
1261      * Default: {@code en}
1262      *
1263      * @return The Locale tag for the documentation set.
1264      */
1265     public String getLocaleTag() {
1266         return localeTag;
1267     }
1268 
1269     /**
1270      * Location of the man page XSL stylesheet customization file,
1271      * relative to the build directory.
1272      *
1273      * <br>
1274      *
1275      * docbkx-tools element: &lt;manpagesCustomization&gt;
1276      */
1277     private String manpagesCustomization = "docbkx-stylesheets/man/coredoc.xsl";
1278 
1279     /**
1280      * Get the location of the man page XSL stylesheet customization file.
1281      *
1282      * <br>
1283      *
1284      * Value: {@code ${project.build.directory}/docbkx-stylesheets/man/coredoc.xsl}
1285      *
1286      * <br>
1287      *
1288      * docbkx-tools element: &lt;manpagesCustomization&gt;
1289      *
1290      * @return The location of the man page XSL stylesheet.
1291      */
1292     public final File getManpagesCustomization() {
1293         return new File(getBuildDirectory(), manpagesCustomization);
1294     }
1295 
1296     /**
1297      * Version of the Maven assembly plugin to use.
1298      */
1299     @Parameter
1300     private String mavenAssemblyVersion;
1301 
1302     /**
1303      * Get the version of the Maven dependency plugin to use.
1304      * @return The version of the Maven dependency plugin to use.
1305      */
1306     public String getMavenAssemblyVersion() {
1307         return getVersionProperty(mavenAssemblyVersion, "mavenAssemblyVersion");
1308     }
1309 
1310     /**
1311      * Version of the Maven dependency plugin to use.
1312      */
1313     @Parameter
1314     private String mavenDependencyVersion;
1315 
1316     /**
1317      * Get the version of the Maven dependency plugin to use.
1318      * @return The version of the Maven dependency plugin to use.
1319      */
1320     public String getMavenDependencyVersion() {
1321         return getVersionProperty(mavenDependencyVersion, "mavenDependencyVersion");
1322     }
1323 
1324     /**
1325      * Version of the Maven filtering library to use.
1326      */
1327     @Parameter
1328     private String mavenFilteringVersion;
1329 
1330     /**
1331      * Get the version of the Maven filtering library to use.
1332      * <br>
1333      * This is used as a workaround for
1334      * <a href="https://jira.codehaus.org/browse/MSHARED-325">MSHARED-325</a>.
1335      *
1336      * @return The version of the Maven filtering library to use.
1337      */
1338     public String getMavenFilteringVersion() {
1339         return getVersionProperty(mavenFilteringVersion, "mavenFilteringVersion");
1340     }
1341 
1342     /**
1343      * Maven resources plugin version.
1344      * Executions seem to hit an NPE when the version is not specified.
1345      */
1346     @Parameter
1347     private String mavenResourcesVersion;
1348 
1349     /**
1350      * Get the Maven resources plugin version.
1351      * Executions seem to hit an NPE when the version is not specified.
1352      *
1353      * @return The Maven resources plugin version.
1354      */
1355     public String getMavenResourcesVersion() {
1356         return getVersionProperty(mavenResourcesVersion, "mavenResourcesVersion");
1357     }
1358 
1359     /**
1360      * Maximum height for PNG images used in PDF, in inches.
1361      */
1362     @Parameter(defaultValue = "5")
1363     private int maxImageHeightInInches;
1364 
1365     /**
1366      * Get maximum height for PNG images used in PDF, in inches.
1367      *
1368      * @return Maximum height for PNG images used in PDF, in inches.
1369      */
1370     public int getMaxImageHeightInInches() {
1371         return maxImageHeightInInches;
1372     }
1373 
1374     /**
1375      * Overwrite the copy of DocBook sources if it exists.
1376      */
1377     @Parameter(defaultValue = "true")
1378     private boolean overwriteModifiableCopy;
1379 
1380     /**
1381      * Whether to overwrite the copy of DocBook sources if it exists.
1382      *
1383      * <br>
1384      *
1385      * One of the first things the plugin does when preparing DocBook sources
1386      * is to make a working copy of the files that is separate from the sources.
1387      * This allows the plugin to make changes to the files as necessary.
1388      *
1389      * <br>
1390      *
1391      * If for some reason you must provide the copy yourself,
1392      * and your copy must be in the {@code docbkxModifiableSourcesDirectory},
1393      * then you can set this to {@code false}
1394      * to prevent the plugin from replacing the copy.
1395      * The plugin will then pre-process the copy, however,
1396      * so expect the files in the modifiable copy to be changed.
1397      *
1398      * <br>
1399      *
1400      * Default: true
1401      *
1402      * @return Whether to overwrite the copy of DocBook sources if it exists.
1403      */
1404     public boolean doOverwriteModifiableCopy() {
1405         return overwriteModifiableCopy;
1406     }
1407 
1408     /**
1409      * Overwrite project files with shared content.
1410      */
1411     @Parameter(defaultValue = "true", property = "overwriteProjectFilesWithSharedContent")
1412     private boolean overwriteProjectFilesWithSharedContent;
1413 
1414     /**
1415      * Whether to overwrite project files with shared content.
1416      *
1417      * <br>
1418      *
1419      * Default: true
1420      *
1421      * @return Whether to overwrite project files with shared content.
1422      */
1423     public boolean doOverwriteProjectFilesWithSharedContent() {
1424         return overwriteProjectFilesWithSharedContent;
1425     }
1426 
1427     /**
1428      * Get path name in UNIX format.
1429      *
1430      * @param file Path to return in UNIX format.
1431      * @return The path in UNIX format.
1432      */
1433     public String path(final File file) {
1434         String result = "";
1435         if (file != null) {
1436             result = FilenameUtils.separatorsToUnix(file.getPath());
1437         }
1438         return result;
1439     }
1440 
1441     /**
1442      * Version of the PlantUML artifact to use.
1443      */
1444     @Parameter
1445     private String plantUmlVersion;
1446 
1447     /**
1448      * Get the version of the PlantUML artifact.
1449      *
1450      * @return The version of the PlantUML artifact.
1451      */
1452     public String getPlantUmlVersion() {
1453         return getVersionProperty(plantUmlVersion, "plantUmlVersion");
1454     }
1455 
1456     /**
1457      * The version of Plexus Utils used by the XCite Maven plugin.
1458      */
1459     @Parameter
1460     private String plexusUtilsVersion;
1461 
1462     /**
1463      * Return the version of Plexus Utils used by the XCite Maven plugin.
1464      *
1465      * @return The version of Plexus Utils used by the XCite Maven plugin.
1466      */
1467     public String getPlexusUtilsVersion() {
1468         return getVersionProperty(plexusUtilsVersion, "plexusUtilsVersion");
1469     }
1470 
1471     /**
1472      * The Maven {@code BuildPluginManager} object.
1473      */
1474     @Component
1475     private BuildPluginManager pluginManager;
1476 
1477     /**
1478      * Get the Maven {@code BuildPluginManager} object.
1479      *
1480      * @return The Maven {@code BuildPluginManager} object.
1481      */
1482     public BuildPluginManager getPluginManager() {
1483         return pluginManager;
1484     }
1485 
1486     /**
1487      * CSS file for the pre-site version of the HTML,
1488      * relative to the build directory.
1489      */
1490     private String preSiteCssFileName = "coredoc.css";
1491 
1492     /**
1493      * Get the CSS file for the pre-site version of the HTML.
1494      *
1495      * <br>
1496      *
1497      * Value: {@code ${project.build.directory}/coredoc.css}
1498      *
1499      * @return The CSS file.
1500      */
1501     public final File getPreSiteCss() {
1502         return new File(getBuildDirectory(), preSiteCssFileName);
1503     }
1504 
1505     /**
1506      * The {@code MavenProject} object, which is read-only.
1507      */
1508     @Parameter(property = "project", required = true, readonly = true)
1509     private MavenProject project;
1510 
1511     /**
1512      * Get the {@code MavenProject} object.
1513      *
1514      * @return The {@code MavenProject} object.
1515      */
1516     public MavenProject getProject() {
1517         return project;
1518     }
1519 
1520     /**
1521      * Short name of the project, such as OpenAM, OpenDJ, OpenIDM.
1522      */
1523     @Parameter(property = "projectName", required = true)
1524     private String projectName;
1525 
1526     /**
1527      * Short name of the project, such as OpenAM, OpenDJ, OpenIDM.
1528      *
1529      * @return The short name of the project.
1530      */
1531     public String getProjectName() {
1532         return projectName;
1533     }
1534 
1535     /**
1536      * Project version.
1537      */
1538     @Parameter(property = "projectVersion", required = true)
1539     private String projectVersion;
1540 
1541     /**
1542      * Get the project version.
1543      *
1544      * @return The project version.
1545      */
1546     public String getProjectVersion() {
1547         return projectVersion;
1548     }
1549 
1550     /**
1551      * CSS file for the release version of the HTML,
1552      * relative to the build directory.
1553      */
1554     private String releaseCssFileName = "dfo.css";
1555 
1556     /**
1557      * Get the CSS file for the release version of the HTML.
1558      *
1559      * <br>
1560      *
1561      * Value: {@code ${project.build.directory}/dfo.css}
1562      *
1563      * @return The CSS file.
1564      */
1565     public final File getReleaseCss() {
1566         return new File(getBuildDirectory(), releaseCssFileName);
1567     }
1568 
1569     /**
1570      * Software release date.
1571      */
1572     @Parameter(property = "releaseDate")
1573     private String releaseDate;
1574 
1575     /**
1576      * Get the software release date.
1577      *
1578      * <br>
1579      *
1580      * Default: now
1581      *
1582      * @return The software release date.
1583      */
1584     public String getReleaseDate() {
1585         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
1586         return releaseDate == null || releaseDate.isEmpty() ? format.format(new Date()) : releaseDate;
1587     }
1588 
1589     /**
1590      * File system directory for release layout documentation,
1591      * relative to the build directory.
1592      */
1593     @Parameter(defaultValue = "release")
1594     private String releaseDirectory;
1595 
1596     /**
1597      * Get the file system directory for release layout documentation.
1598      *
1599      * <br>
1600      *
1601      * Default: {@code ${project.build.directory}/release}
1602      *
1603      * @return {@link #releaseDirectory}
1604      */
1605     public final File getReleaseDirectory() {
1606         return new File(getBuildDirectory(), releaseDirectory);
1607     }
1608 
1609     /**
1610      * Favicon link element for the release version of the HTML.
1611      */
1612     @Parameter(defaultValue = "<link rel=\"shortcut icon\" href=\"https://wrensecurity.org/favicon.ico\">")
1613     private String releaseFaviconLink;
1614 
1615     /**
1616      * Get the favicon link element for the release version of the HTML.
1617      *
1618      * @return The link element.
1619      */
1620     public final String getReleaseFaviconLink() {
1621         return releaseFaviconLink;
1622     }
1623 
1624     /**
1625      * Version for this release.
1626      */
1627     @Parameter(property = "releaseVersion", required = true)
1628     private String releaseVersion;
1629 
1630     /**
1631      * Get the version for this release.
1632      *
1633      * @return The version for this release.
1634      */
1635     public final String getReleaseVersion() {
1636         return releaseVersion;
1637     }
1638 
1639     /**
1640      * Get the path to the directory to hold the release version documents,
1641      * such as {@code ${project.build.directory}/release/1.0.0}.
1642      *
1643      * @return The path to the release version directory.
1644      */
1645     public final String getReleaseVersionPath() {
1646         return getReleaseDirectory().getPath() + File.separator + getReleaseVersion();
1647     }
1648 
1649     /**
1650      * File system directory for arbitrary documentation set resources,
1651      * relative to the modifiable sources directory.
1652      */
1653     @Parameter(defaultValue = "resources")
1654     private String resourcesDirectory;
1655 
1656     /**
1657      * Path to arbitrary documentation set resources,
1658      * relative to the modifiable sources directory.
1659      *
1660      * <br>
1661      *
1662      * Default: {@code resources}
1663      *
1664      * @return The resources directory path, relative to the modifiable sources directory.
1665      */
1666     public String getRelativeResourcesDirectoryPath() {
1667         return resourcesDirectory;
1668     }
1669 
1670     /**
1671      * Directory for arbitrary documentation set resources.
1672      *
1673      * <br>
1674      *
1675      * Default: {@code ${basedir}/src/main/docbkx/resources}
1676      *
1677      * @return The resources directory.
1678      */
1679     public File getResourcesDirectory() {
1680         return new File(getDocbkxModifiableSourcesDirectory(), resourcesDirectory);
1681     }
1682 
1683     /**
1684      * Whether to run the ForgeRock link tester plugin.
1685      */
1686     @Parameter(defaultValue = "true", property = "runLinkTester")
1687     private String runLinkTester;
1688 
1689     /**
1690      * Whether to run the ForgeRock link tester plugin.
1691      *
1692      * <br>
1693      *
1694      * You only need to run the link test from the top level of a project.
1695      *
1696      * <br>
1697      *
1698      * Default: {@code "true"}
1699      *
1700      * @return Whether to run the ForgeRock link tester plugin.
1701      */
1702     public String runLinkTester() {
1703         return runLinkTester;
1704     }
1705 
1706     /**
1707      * The {@code MavenSession} object, which is read-only.
1708      */
1709     @Parameter(property = "session", required = true, readonly = true)
1710     private MavenSession session;
1711 
1712     /**
1713      * Get the {@code MavenSession} object.
1714      * @return The {@code MavenSession} object.
1715      */
1716     public MavenSession getSession() {
1717         return session;
1718     }
1719 
1720     /**
1721      * Location of the single page HTML XSL stylesheet customization file,
1722      * relative to the build directory.
1723      *
1724      * <br>
1725      *
1726      * docbkx-tools element: &lt;htmlCustomization&gt;
1727      */
1728     private String singleHTMLCustomization = "/docbkx-stylesheets/html/coredoc.xsl";
1729 
1730     /**
1731      * Get the location of the single page HTML XSL stylesheet customization file.
1732      *
1733      * <br>
1734      *
1735      * Value: {@code ${project.build.directory}/docbkx-stylesheets/html/coredoc.xsl}
1736      *
1737      * <br>
1738      *
1739      * docbkx-tools element: &lt;htmlCustomization&gt;
1740      *
1741      * @return The location of the single-page HTML XSL stylesheet.
1742      */
1743     public final File getSingleHTMLCustomization() {
1744         return new File(getBuildDirectory(), singleHTMLCustomization);
1745     }
1746 
1747     /**
1748      * File system directory for site content, relative to the build directory.
1749      */
1750     @Parameter(defaultValue = "site")
1751     private String siteDirectory;
1752 
1753     /**
1754      * Get the file system directory for site content.
1755      *
1756      * <br>
1757      *
1758      * Default: {@code ${project.build.directory}/site}
1759      *
1760      * @return The file system directory for site content.
1761      */
1762     public final File getSiteDirectory() {
1763         return new File(getBuildDirectory(), siteDirectory);
1764     }
1765 
1766     /**
1767      * Whether the ForgeRock link tester plugin should skip checking
1768      * that external URLs are valid.
1769      *
1770      * <br>
1771      *
1772      * See the {@code skipUrls} parameter of the <a
1773      * href="https://github.com/aldaris/docbook-linktester/">linktester plugin</a>.
1774      */
1775     @Parameter(defaultValue = "false", property = "skipLinkCheck")
1776     private String skipLinkCheck;
1777 
1778     /**
1779      * Whether the ForgeRock link tester plugin should skip checking
1780      * that external URLs are valid.
1781      *
1782      * <br>
1783      *
1784      * See the {@code skipUrls} parameter of the <a
1785      * href="https://github.com/aldaris/docbook-linktester/">linktester plugin</a>.
1786      *
1787      * <br>
1788      *
1789      * Default: {@code false}
1790      *
1791      * @return Whether to test that external URLs are valid.
1792      */
1793     public String skipLinkCheck() {
1794         return skipLinkCheck;
1795     }
1796 
1797     /**
1798      * Regex patterns of URLs to skip when checking external links.
1799      *
1800      * <br>
1801      *
1802      * See the {@code skipUrlPatterns} parameter of the <a
1803      * href="https://github.com/aldaris/docbook-linktester/">linktester plugin</a>.
1804      */
1805     @Parameter
1806     private String[] skipUrlPatterns;
1807 
1808     /**
1809      * Get regex patterns of URLs to skip when checking external links.
1810      *
1811      * <br>
1812      *
1813      * Default: {@code null}
1814      *
1815      * @return Regex patterns of URLs to skip when checking external links.
1816      */
1817     public String[] getSkipUrlPatterns() {
1818         return skipUrlPatterns;
1819     }
1820 
1821     /**
1822      * Whether to build from pre-processed DocBook XML sources.
1823      */
1824     @Parameter(defaultValue = "false", property = "usePreProcessedSources")
1825     private boolean usePreProcessedSources;
1826 
1827     /**
1828      * Whether to build from pre-processed DocBook XML sources.
1829      *
1830      * <p>
1831      *
1832      * Default: {@code false}
1833      *
1834      * @return True if {@code docbkxSourceDirectory} contains fully pre-processed sources.
1835      */
1836     public boolean doUsePreProcessedSources() {
1837         return usePreProcessedSources;
1838     }
1839 
1840     /**
1841      * Whether &lt;programlisting&gt; content has syntax highlighting.
1842      *
1843      * <br>
1844      *
1845      * docbkx-tools element: &lt;highlightSource&gt;
1846      */
1847     private String useSyntaxHighlighting = "1";
1848 
1849     /**
1850      * Whether &lt;programlisting&gt; content has syntax highlighting.
1851      *
1852      * <br>
1853      *
1854      * Value: {@code 1} (true)
1855      *
1856      * <br>
1857      *
1858      * docbkx-tools element: &lt;highlightSource&gt;
1859      *
1860      * @return Where program listings use syntax highlighting.
1861      */
1862     public final String useSyntaxHighlighting() {
1863         return useSyntaxHighlighting;
1864     }
1865 
1866     /**
1867      * Location of the main CSS for webhelp documents,
1868      * relative to the build directory.
1869      */
1870     private String webhelpCss = "docbkx-stylesheets/webhelp/positioning.css";
1871 
1872     /**
1873      * Get the location of the main CSS file for webhelp documents.
1874      *
1875      * <br>
1876      *
1877      * Value: {@code ${project.build.dir}/docbkx-stylesheets/webhelp/positioning.css}
1878      *
1879      * @return The main CSS file for webhelp documents.
1880      */
1881     public final File getWebHelpCss() {
1882         return new File(getBuildDirectory(), webhelpCss);
1883     }
1884 
1885     /**
1886      * Location of the webhelp XSL stylesheet customization file, relative to
1887      * the build
1888      * directory.
1889      *
1890      * <br>
1891      *
1892      * docbkx-tools element: &lt;webhelpCustomization&gt;
1893      */
1894     private String webhelpCustomization = "docbkx-stylesheets/webhelp/coredoc.xsl";
1895 
1896     /**
1897      * Get the location of the webhelp XSL stylesheet customization file.
1898      *
1899      * <br>
1900      *
1901      * Value: {@code ${project.build.dir}/docbkx-stylesheets/webhelp/coredoc.xsl}
1902      *
1903      * <br>
1904      *
1905      * docbkx-tools element: &lt;webhelpCustomization&gt;
1906      *
1907      * @return The location of the webhelp XSL stylesheet.
1908      */
1909     public final File getWebHelpCustomization() {
1910         return new File(getBuildDirectory(), webhelpCustomization);
1911     }
1912 
1913     /**
1914      * Location of the logo image for webhelp documents,
1915      * relative to the build directory.
1916      */
1917     private String webhelpLogo = "docbkx-stylesheets/webhelp/logo.png";
1918 
1919     /**
1920      * Get the location of the logo image for webhelp documents.
1921      *
1922      * <br>
1923      *
1924      * Value: {@code ${project.build.dir}/docbkx-stylesheets/webhelp/logo.png}
1925      *
1926      * @return The logo image for webhelp documents.
1927      */
1928     public final File getWebHelpLogo() {
1929         return new File(getBuildDirectory(), webhelpLogo);
1930     }
1931 
1932     /**
1933      * Version of the XCite Maven plugin to use.
1934      */
1935     @Parameter
1936     private String xCiteVersion;
1937 
1938     /**
1939      * Return the version of the XCite Maven plugin to use.
1940      *
1941      * @return The version of the XCite Maven plugin to use.
1942      */
1943     public String getXCiteVersion() {
1944         return getVersionProperty(xCiteVersion, "xCiteVersion");
1945     }
1946 
1947     /**
1948      * Location of the XHTML5 XSL stylesheet customization file,
1949      * relative to the build directory.
1950      *
1951      * <br>
1952      *
1953      * docbkx-tools element: &lt;xhtml5Customization&gt;
1954      */
1955     private String xhtml5Customization = "docbkx-stylesheets/xhtml5/coredoc.xsl";
1956 
1957     /**
1958      * Location of the XHTML5 XSL stylesheet customization file,
1959      * relative to the build directory.
1960      *
1961      * <br>
1962      *
1963      * Value: {@code ${project.build.directory}/docbkx-stylesheets/xhtml5/coredoc.xsl}
1964      *
1965      * <br>
1966      *
1967      * Default: {@code ${project.build.directory}/docbkx-stylesheets/xhtml5/coredoc.xsl}
1968      *
1969      * <br>
1970      *
1971      * docbkx-tools element: &lt;xhtml5Customization&gt;
1972      *
1973      * @return The location of the XHTML5 XSL stylesheet.
1974      */
1975     public final File getXhtml5Customization() {
1976         return new File(getBuildDirectory(), xhtml5Customization);
1977     }
1978 
1979     /**
1980      * Location of the HtmlForBootstrap XSL stylesheet customization file,
1981      * relative to the build directory.
1982      *
1983      * <br>
1984      *
1985      * docbkx-tools element: &lt;bootstrapCustomization&gt;
1986      */
1987     private String bootstrapCustomization =
1988             "docbkx-stylesheets/bootstrap/coredoc.xsl";
1989     /**
1990      * Get the location of the HtmlForBootstrap XSL stylesheet customization file.
1991      *
1992      * <br>
1993      *
1994      * Default: {@code ${project.build.directory}/docbkx-stylesheets/bootstrap/coredoc.xsl}
1995      *
1996      * <br>
1997      *
1998      * docbkx-tools element: &lt;bootstrapCustomization&gt;
1999      *
2000      * @return The location of the HtmlForBootstrap XSL stylesheet.
2001      */
2002     public final File getBootstrapCustomization() {
2003         return new File(getBuildDirectory(), bootstrapCustomization);
2004     }
2005 }