View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.javadoc;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.nio.charset.Charset;
24  import java.nio.charset.StandardCharsets;
25  import java.nio.file.DirectoryStream;
26  import java.nio.file.Files;
27  import java.nio.file.Path;
28  import java.util.ArrayList;
29  import java.util.Collection;
30  import java.util.Collections;
31  import java.util.List;
32  
33  import org.apache.maven.reporting.MavenReportException;
34  import org.codehaus.plexus.languages.java.version.JavaVersion;
35  import org.codehaus.plexus.util.cli.Commandline;
36  
37  /**
38   * Helper class to compute and write data used to detect a
39   * stale javadoc.
40   */
41  public class StaleHelper {
42  
43      /**
44       * Compute the encoding of the stale javadoc
45       *
46       * @return the the encoding of the stale data
47       */
48      private static Charset getDataCharset() {
49          if (JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("9")
50                  && JavaVersion.JAVA_SPECIFICATION_VERSION.isBefore("12")) {
51              return StandardCharsets.UTF_8;
52          } else {
53              return Charset.defaultCharset();
54          }
55      }
56  
57      /**
58       * Compute the data used to detect a stale javadoc
59       *
60       * @param cmd the command line
61       * @return the stale data
62       * @throws MavenReportException if an error occurs
63       */
64      public static List<String> getStaleData(Commandline cmd) throws MavenReportException {
65          try {
66              List<String> ignored = new ArrayList<>();
67              List<String> options = new ArrayList<>();
68              Path dir = cmd.getWorkingDirectory().toPath().toAbsolutePath().normalize();
69              String[] args = cmd.getArguments();
70              Collections.addAll(options, args);
71  
72              for (String arg : args) {
73                  if (arg.startsWith("@")) {
74                      String name = arg.substring(1);
75                      options.addAll(Files.readAllLines(dir.resolve(name), getDataCharset()));
76                      ignored.add(name);
77                  }
78              }
79              List<String> state = new ArrayList<>(options);
80              boolean cp = false;
81              boolean sp = false;
82              for (String arg : options) {
83                  if (cp) {
84                      String s = unquote(arg);
85                      for (String ps : s.split(File.pathSeparator)) {
86                          Path p = dir.resolve(ps);
87                          state.add(p + " = " + lastmod(p));
88                      }
89                  } else if (sp) {
90                      String s = unquote(arg);
91                      for (String ps : s.split(File.pathSeparator)) {
92                          Path p = dir.resolve(ps);
93                          for (Path c : walk(p)) {
94                              if (Files.isRegularFile(c)) {
95                                  state.add(c + " = " + lastmod(c));
96                              }
97                          }
98                          state.add(p + " = " + lastmod(p));
99                      }
100                 }
101                 cp = "-classpath".equals(arg);
102                 sp = "-sourcepath".equals(arg);
103             }
104             for (Path p : walk(dir)) {
105                 if (Files.isRegularFile(p) && !ignored.contains(p.getFileName().toString())) {
106                     state.add(p + " = " + lastmod(p));
107                 }
108             }
109             return state;
110         } catch (Exception e) {
111             throw new MavenReportException("Unable to compute stale date", e);
112         }
113     }
114 
115     /**
116      * Write the data used to detect a stale javadoc
117      *
118      * @param cmd the command line
119      * @param path the stale data path
120      * @throws MavenReportException if an error occurs
121      */
122     public static void writeStaleData(Commandline cmd, Path path) throws MavenReportException {
123         try {
124             List<String> curdata = getStaleData(cmd);
125             Files.createDirectories(path.getParent());
126             Files.write(path, curdata, getDataCharset());
127         } catch (IOException e) {
128             throw new MavenReportException("Error checking stale data", e);
129         }
130     }
131 
132     private static Collection<Path> walk(Path dir) {
133         Collection<Path> paths = new ArrayList<>();
134         try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(dir)) {
135             for (Path p : directoryStream) {
136                 paths.add(p);
137             }
138             return paths;
139         } catch (IOException e) {
140             throw new RuntimeException(e);
141         }
142     }
143 
144     private static String unquote(String s) {
145         if (s.startsWith("'") && s.endsWith("'")) {
146             return s.substring(1, s.length() - 1).replaceAll("\\\\'", "'");
147         } else {
148             return s;
149         }
150     }
151 
152     private static long lastmod(Path p) {
153         try {
154             return Files.getLastModifiedTime(p).toMillis();
155         } catch (IOException e) {
156             return 0;
157         }
158     }
159 }