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 2015 ForgeRock AS.
15   */
16  
17  package org.forgerock.doc.maven.post;
18  
19  import org.apache.commons.io.FileUtils;
20  import org.apache.commons.io.filefilter.FileFilterUtils;
21  import org.apache.maven.plugin.MojoExecutionException;
22  import org.forgerock.doc.maven.AbstractDocbkxMojo;
23  
24  import java.io.File;
25  import java.io.IOException;
26  
27  /**
28   * Fix man page file locations.
29   */
30  public class ManpagePost extends AbstractDocbkxMojo {
31  
32      /**
33       * The Mojo that holds configuration and related methods.
34       */
35      private AbstractDocbkxMojo m;
36  
37      /**
38       * Constructor setting the Mojo that holds the configuration.
39       *
40       * @param mojo The Mojo that holds the configuration.
41       */
42      public ManpagePost(final AbstractDocbkxMojo mojo) {
43          m = mojo;
44      }
45  
46      /**
47       * Fix man page file locations.
48       * <br>
49       * Man page generation replaces spaces in path name with underscores.
50       * As a result, if man pages are built in a project directory like
51       * {@code /path/to/My Doc Project},
52       * then the generated man pages end up by default in
53       * {@code /path/to/My_Doc_Project/target/docbkx/manpages}.
54       * <br>
55       * This method copies the result to the expected location.
56       * <br>
57       * This method then attempts to remove the extra generated directory,
58       * though failure to remove the extra directory only logs an informational message
59       * and does no throw an exception.
60       *
61       * @throws MojoExecutionException   Failed to copy files.
62       */
63      public void execute() throws MojoExecutionException {
64          File manPageOutputDir = new File(m.getDocbkxOutputDirectory(), "manpages");
65          File generatedManPageDir = new File(manPageOutputDir.getAbsolutePath().replace(' ', '_'));
66          if (generatedManPageDir.equals(manPageOutputDir)) {
67              return; // Nothing to copy, and do not delete the man page directory.
68          }
69          if (!generatedManPageDir.exists() || !hasChildren(generatedManPageDir)) {
70              m.getLog().info("No man pages found in " + generatedManPageDir.getAbsolutePath());
71              return; // No man pages. Nothing to do.
72          }
73  
74          // The generated man page dir is different from the expected man page output dir,
75          // so copy the content to the expected location and try to delete the generated dir.
76          try {
77              FileUtils.copyDirectory(generatedManPageDir, manPageOutputDir, FileFilterUtils.trueFileFilter());
78          } catch (IOException e) {
79              throw new MojoExecutionException(e.getMessage(), e);
80          }
81  
82          File topGeneratedDirWithUnderscore = getTopAncestorWithUnderscore(generatedManPageDir);
83          try {
84              FileUtils.deleteDirectory(topGeneratedDirWithUnderscore);
85          } catch (IOException e) {
86              m.getLog().info("Failed to delete generated man page dir: " + generatedManPageDir + e.getMessage());
87          }
88      }
89  
90      /**
91       * Returns true if the specified directory has children.
92       * @param directory The directory to check.
93       * @return True if the specified directory has children.
94       */
95      private boolean hasChildren(final File directory) {
96          String[] children = directory.list();
97          return children.length > 0;
98      }
99  
100     /**
101      * Returns the top ancestor directory that contains an underscore in the path.
102      * @param directory Returns this directory or an ancestor.
103      * @return The top ancestor directory that contains an underscore in the path.
104      */
105     private File getTopAncestorWithUnderscore(final File directory) {
106         File topAncestorWithUnderscore = directory;
107         while (topAncestorWithUnderscore.getParent().contains("_")) {
108             topAncestorWithUnderscore = topAncestorWithUnderscore.getParentFile();
109         }
110         return topAncestorWithUnderscore;
111     }
112 }