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.jxr;
20
21 import java.io.IOException;
22 import java.nio.file.Path;
23 import java.nio.file.Paths;
24 import java.util.List;
25 import java.util.Locale;
26
27 import org.apache.maven.jxr.ant.DirectoryScanner;
28 import org.apache.maven.jxr.pacman.PackageManager;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33 * Main entry point into Maven used to kick off the XReference code building.
34 *
35 * @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
36 */
37 public class JXR {
38 private static final Logger LOGGER = LoggerFactory.getLogger(JXR.class);
39
40 private final PackageManager pkgmgr;
41
42 /**
43 * Handles taking .java files and changing them into HTML. "More than meets
44 * the eye!" :)
45 */
46 private final JavaCodeTransform transformer;
47
48 /**
49 * The default list of include patterns to use.
50 */
51 private static final String[] DEFAULT_INCLUDES = {"**/*.java"};
52
53 /**
54 * Path to destination.
55 */
56 private Path destDir;
57
58 private Locale locale;
59
60 private String inputEncoding;
61
62 private String outputEncoding;
63
64 /**
65 * Relative path to javadocs, suitable for hyperlinking.
66 */
67 private Path javadocLinkDir;
68
69 /**
70 * The revision of the module currently being processed.
71 */
72 private String revision;
73
74 /**
75 * The list of exclude patterns to use.
76 */
77 private String[] excludes = null;
78
79 /**
80 * The list of include patterns to use.
81 */
82 private String[] includes = DEFAULT_INCLUDES;
83
84 public JXR(PackageManager pkgmgr, JavaCodeTransform transformer) {
85 this.pkgmgr = pkgmgr;
86 this.transformer = transformer;
87 }
88
89 /**
90 * Now that we have instantiated everything. Process this JXR task.
91 *
92 * @param packageManager package manager
93 * @param sourceDir source directory.
94 * @param bottom bottom text
95 * @throws IOException on transformation error
96 */
97 public void processPath(PackageManager packageManager, Path sourceDir, String bottom) throws IOException {
98 DirectoryScanner ds = new DirectoryScanner();
99 // I'm not sure why we don't use the directoryScanner in packageManager,
100 // but since we don't we need to set includes/excludes here as well
101 ds.setExcludes(excludes);
102 ds.setIncludes(includes);
103 ds.addDefaultExcludes();
104
105 ds.setBasedir(sourceDir.toString());
106 ds.scan();
107
108 // now get the list of included files
109
110 String[] files = ds.getIncludedFiles();
111
112 for (String file : files) {
113 Path sourceFile = sourceDir.resolve(file);
114
115 if (isJavaFile(sourceFile.toString())) {
116 String newFileName = file.replaceFirst(".java$", ".html");
117
118 transform(sourceFile, this.destDir.resolve(newFileName), bottom);
119 }
120 }
121 }
122
123 /**
124 * Check to see if the file is a Java source file.
125 *
126 * @param filename The name of the file to check
127 * @return {@code true} if the file is a Java file
128 */
129 public static boolean isJavaFile(String filename) {
130 return filename.endsWith(".java");
131 }
132
133 /**
134 * Checks to see if the file is an HTML file.
135 *
136 * @param filename The name of the file to check
137 * @return {@code true} if the file is an HTML file
138 */
139 public static boolean isHtmlFile(String filename) {
140 return filename.endsWith(".html");
141 }
142
143 /**
144 * Sets the destination.
145 *
146 * @param dest destination
147 */
148 public void setDest(Path dest) {
149 this.destDir = dest;
150 }
151
152 /**
153 * Sets the locale.
154 *
155 * @param locale locale
156 */
157 public void setLocale(Locale locale) {
158 this.locale = locale;
159 }
160
161 /**
162 * Sets the input encoding.
163 *
164 * @param inputEncoding input encoding
165 */
166 public void setInputEncoding(String inputEncoding) {
167 this.inputEncoding = inputEncoding;
168 }
169
170 /**
171 * Sets the output encoding.
172 *
173 * @param outputEncoding output encoding
174 */
175 public void setOutputEncoding(String outputEncoding) {
176 this.outputEncoding = outputEncoding;
177 }
178
179 /**
180 * Sets the relative path to javadocs.
181 * @param javadocLinkDir path to javadocs
182 */
183 public void setJavadocLinkDir(Path javadocLinkDir) {
184 // get a relative link to the javadocs
185 this.javadocLinkDir = javadocLinkDir;
186 }
187
188 /**
189 * Sets the revision.
190 *
191 * @param revision revision
192 */
193 public void setRevision(String revision) {
194 this.revision = revision;
195 }
196
197 /**
198 * Performs the cross-referencing.
199 *
200 * @param sourceDirs source directories
201 * @param templateDir template directory
202 * @param windowTitle window title
203 * @param docTitle document title
204 * @param bottom bottom text
205 * @throws IOException on I/O error
206 * @throws JxrException on Velocity error
207 */
208 public void xref(List<String> sourceDirs, String templateDir, String windowTitle, String docTitle, String bottom)
209 throws IOException, JxrException {
210 pkgmgr.setExcludes(excludes);
211 pkgmgr.setIncludes(includes);
212
213 // go through each source directory and xref the java files
214 for (String dir : sourceDirs) {
215 Path path = Paths.get(dir).toRealPath();
216
217 pkgmgr.process(path);
218
219 processPath(pkgmgr, path, bottom);
220 }
221
222 // once we have all the source files xref'd, create the index pages
223 DirectoryIndexer indexer = new DirectoryIndexer(pkgmgr, destDir.toString());
224 indexer.setOutputEncoding(outputEncoding);
225 indexer.setTemplateDir(templateDir);
226 indexer.setWindowTitle(windowTitle);
227 indexer.setDocTitle(docTitle);
228 indexer.setBottom(bottom);
229 indexer.process();
230 }
231
232 // ----------------------------------------------------------------------
233 // private methods
234 // ----------------------------------------------------------------------
235 /**
236 * Given a source file transform it into HTML and write it to the
237 * destination (dest) file.
238 *
239 * @param sourceFile The java source file
240 * @param destFile The directory to put the HTML into
241 * @param bottom The bottom footer text just as in the package pages
242 * @throws IOException if the transform can't happen for some reason
243 */
244 private void transform(Path sourceFile, Path destFile, String bottom) throws IOException {
245 LOGGER.debug(sourceFile + " -> " + destFile);
246
247 // get a relative link to the javadocs
248 Path javadoc = javadocLinkDir != null ? getRelativeLink(destFile.getParent(), javadocLinkDir) : null;
249 transformer.transform(
250 sourceFile, destFile, locale, inputEncoding, outputEncoding, javadoc, this.revision, bottom);
251 }
252
253 /**
254 * Creates a relative link from one directory to another.
255 *
256 * Example:
257 * given {@code /foo/bar/baz/oink}
258 * and {@code /foo/bar/schmoo}
259 *
260 * this method will return a string of {@code "../../schmoo/"}
261 *
262 * @param fromDir The directory from which the link is relative.
263 * @param toDir The directory into which the link points.
264 * @return a String of format {@code "../../schmoo/"}
265 */
266 private static Path getRelativeLink(Path fromDir, Path toDir) {
267 return fromDir.relativize(toDir);
268 }
269
270 public void setExcludes(String[] excludes) {
271 this.excludes = excludes;
272 }
273
274 public void setIncludes(String[] includes) {
275 if (includes == null) {
276 // We should not include non-java files, so we use a sensible default pattern
277 this.includes = DEFAULT_INCLUDES;
278 } else {
279 this.includes = includes;
280 }
281 }
282 }