1 package org.apache.maven.jxr;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import org.apache.maven.jxr.ant.DirectoryScanner;
23 import org.apache.maven.jxr.log.Log;
24 import org.apache.maven.jxr.pacman.FileManager;
25 import org.apache.maven.jxr.pacman.PackageManager;
26
27 import java.io.File;
28 import java.io.FileNotFoundException;
29 import java.io.IOException;
30 import java.util.Iterator;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.Locale;
34
35 /**
36 * Main entry point into Maven used to kick off the XReference code building.
37 *
38 * @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
39 * @version $Id: JXR.java 692692 2008-09-06 17:34:46Z hboutemy $
40 */
41 public class JXR
42 {
43 /**
44 * The Log.
45 */
46 private Log log;
47
48 /**
49 * Description of the Notice.
50 */
51 public static final String NOTICE = "This page was automatically generated by "
52 + "<a href=\"http://maven.apache.org/\">Maven</a>";
53
54 /**
55 * The default list of include patterns to use.
56 */
57 private static final String[] DEFAULT_INCLUDES = {"**/*.java"};
58
59 /**
60 * Path to destination.
61 */
62 private String dest = "";
63
64 private Locale locale;
65
66 private String inputEncoding;
67
68 private String outputEncoding;
69
70 /**
71 * Relative path to javadocs, suitable for hyperlinking.
72 */
73 private String javadocLinkDir;
74
75 /**
76 * Handles taking .java files and changing them into html. "More than meets
77 * the eye!" :)
78 */
79 private JavaCodeTransform transformer;
80
81 /**
82 * The revision of the module currently being processed.
83 */
84 private String revision;
85
86 /**
87 * The list of exclude patterns to use.
88 */
89 private String[] excludes = null;
90
91 /**
92 * The list of include patterns to use.
93 */
94 private String[] includes = DEFAULT_INCLUDES;
95
96 /**
97 * Now that we have instantiated everything. Process this JXR task.
98 *
99 * @param packageManager
100 * @param source
101 * @throws IOException
102 */
103 public void processPath( PackageManager packageManager, String source )
104 throws IOException
105 {
106 this.transformer = new JavaCodeTransform( packageManager );
107
108 DirectoryScanner ds = new DirectoryScanner();
109 // I'm not sure why we don't use the directoryScanner in packageManager,
110 // but since we don't we need to set includes/excludes here as well
111 ds.setExcludes( excludes );
112 ds.setIncludes( includes );
113 ds.addDefaultExcludes();
114
115 File dir = new File( source );
116
117 if ( !dir.exists() )
118 {
119 if ( !dir.mkdirs() )
120 {
121 throw new IllegalStateException(
122 "Your source directory does not exist and could not be created:" + source );
123 }
124 }
125
126 ds.setBasedir( source );
127 ds.scan();
128
129 //now get the list of included files
130
131 String[] files = ds.getIncludedFiles();
132
133 for ( int i = 0; i < files.length; ++i )
134 {
135 String src = source + System.getProperty( "file.separator" ) + files[i];
136
137 if ( isJavaFile( src ) )
138 {
139 transform( src, getDestination( source, src ) );
140 }
141
142 }
143 }
144
145 /**
146 * Check to see if the file is a Java source file.
147 *
148 * @param filename The name of the file to check
149 * @return <code>true</true> if the file is a Java file
150 */
151 public static boolean isJavaFile( String filename )
152 {
153 File file = new File( filename );
154 return filename.endsWith( ".java" ) && file.length() > 0;
155 }
156
157 /**
158 * Check to see if the file is an HTML file.
159 *
160 * @param filename The name of the file to check
161 * @return <code>true</true> if the file is an HTML file
162 */
163 public static boolean isHtmlFile( String filename )
164 {
165 return filename.endsWith( ".html" );
166 }
167
168 /**
169 * Get the path to the destination files.
170 *
171 * @return The path to the destination files
172 */
173 public String getDest()
174 {
175 return this.dest;
176 }
177
178 /**
179 * @param dest
180 */
181 public void setDest( String dest )
182 {
183 this.dest = dest;
184 }
185
186 /**
187 * @param locale
188 */
189 public void setLocale( Locale locale )
190 {
191 this.locale = locale;
192 }
193
194 /**
195 * @param inputEncoding
196 */
197 public void setInputEncoding( String inputEncoding )
198 {
199 this.inputEncoding = inputEncoding;
200 }
201
202 /**
203 * @param outputEncoding
204 */
205 public void setOutputEncoding( String outputEncoding )
206 {
207 this.outputEncoding = outputEncoding;
208 }
209
210 /**
211 * @param javadocLinkDir
212 */
213 public void setJavadocLinkDir( String javadocLinkDir )
214 {
215 // get a relative link to the javadocs
216 this.javadocLinkDir = javadocLinkDir;
217 }
218
219 /**
220 * @param transformer
221 */
222 public void setTransformer( JavaCodeTransform transformer )
223 {
224 this.transformer = transformer;
225 }
226
227 /**
228 * @param revision
229 */
230 public void setRevision( String revision )
231 {
232 this.revision = revision;
233 }
234
235 /**
236 * @param log
237 */
238 public void setLog( Log log )
239 {
240 this.log = log;
241 }
242
243 /**
244 * @param sourceDirs
245 * @param templateDir
246 * @param windowTitle
247 * @param docTitle
248 * @param bottom
249 * @throws IOException
250 * @throws JxrException
251 */
252 public void xref( List sourceDirs, String templateDir, String windowTitle, String docTitle, String bottom )
253 throws IOException, JxrException
254 {
255 // first collect package and class info
256 FileManager fileManager = new FileManager();
257 fileManager.setEncoding( inputEncoding );
258
259 PackageManager pkgmgr = new PackageManager( log, fileManager );
260 pkgmgr.setExcludes( excludes );
261 pkgmgr.setIncludes( includes );
262
263 // go through each source directory and xref the java files
264 for ( Iterator i = sourceDirs.iterator(); i.hasNext(); )
265 {
266 String path = (String) i.next();
267 path = new File( path ).getCanonicalPath();
268
269 pkgmgr.process( path );
270
271 processPath( pkgmgr, path );
272 }
273
274 // once we have all the source files xref'd, create the index pages
275 DirectoryIndexer indexer = new DirectoryIndexer( pkgmgr, dest );
276 indexer.setOutputEncoding( outputEncoding );
277 indexer.setTemplateDir( templateDir );
278 indexer.setWindowTitle( windowTitle );
279 indexer.setDocTitle( docTitle );
280 indexer.setBottom( bottom );
281 indexer.process( log );
282 }
283
284 // ----------------------------------------------------------------------
285 // private methods
286 // ----------------------------------------------------------------------
287
288 /**
289 * Given a filename get the destination on the filesystem of where to store
290 * the to be generated HTML file. Pay attention to the package name.
291 *
292 * @param source
293 * @param filename
294 * @return A String with the store destination.
295 */
296 private String getDestination( String source, String filename )
297 {
298 //remove the source directory from the filename.
299
300 String dest = filename.substring( source.length(), filename.length() );
301
302 int start = 0;
303 int end = dest.indexOf( ".java" );
304
305 if ( end != -1 )
306 {
307 //remove the .java from the filename
308 dest = dest.substring( start, end );
309 }
310
311 //add the destination directory to the filename.
312 dest = this.getDest() + dest;
313
314 //add .html to the filename
315
316 dest = dest + ".html";
317
318 return dest;
319 }
320
321 /**
322 * Given a source file transform it into HTML and write it to the
323 * destination (dest) file.
324 *
325 * @param source The java source file
326 * @param dest The directory to put the HTML into
327 * @throws IOException Thrown if the transform can't happen for some reason.
328 */
329 private void transform( String source, String dest )
330 throws IOException
331 {
332 log.debug( source + " -> " + dest );
333
334 // get a relative link to the javadocs
335 String javadoc = javadocLinkDir != null ? getRelativeLink( dest, javadocLinkDir ) : null;
336 transformer.transform( source, dest, locale, inputEncoding, outputEncoding, javadoc, this.revision );
337 }
338
339 /**
340 * Creates a relative link from one directory to another.
341 *
342 * Example:
343 * given <code>/foo/bar/baz/oink</code>
344 * and <code>/foo/bar/schmoo</code>
345 *
346 * this method will return a string of <code>"../../schmoo/"</code>
347 *
348 * @param fromDir The directory from which the link is relative.
349 * @param toDir The directory into which the link points.
350 * @return a String of format <code>"../../schmoo/"</code>
351 * @throws java.io.IOException If a problem is encountered while navigating through the directories.
352 */
353 private static String getRelativeLink( String fromDir, String toDir )
354 throws IOException
355 {
356 StringBuffer toLink = new StringBuffer(); // up from fromDir
357 StringBuffer fromLink = new StringBuffer(); // down into toDir
358
359 // create a List of toDir's parent directories
360 List parents = new LinkedList();
361 File f = new File( toDir );
362 f = f.getCanonicalFile();
363 while ( f != null )
364 {
365 parents.add( f );
366 f = f.getParentFile();
367 }
368
369 // walk up fromDir to find the common parent
370 f = new File( fromDir );
371 if ( !f.isDirectory() )
372 {
373 // Passed in a fromDir with a filename on the end - strip it
374 f = f.getParentFile();
375 }
376 f = f.getCanonicalFile();
377 f = f.getParentFile();
378 boolean found = false;
379 while ( f != null && !found )
380 {
381 for ( int i = 0; i < parents.size(); ++i )
382 {
383 File parent = (File) parents.get( i );
384 if ( f.equals( parent ) )
385 {
386 // when we find the common parent, add the subdirectories
387 // down to toDir itself
388 for ( int j = 0; j < i; ++j )
389 {
390 File p = (File) parents.get( j );
391 toLink.insert( 0, p.getName() + "/" );
392 }
393 found = true;
394 break;
395 }
396 }
397 f = f.getParentFile();
398 fromLink.append( "../" );
399 }
400
401 if ( !found )
402 {
403 throw new FileNotFoundException( fromDir + " and " + toDir + " have no common parent." );
404 }
405
406 return fromLink.append( toLink.toString() ).toString();
407 }
408
409 public void setExcludes( String[] excludes )
410 {
411 this.excludes = excludes;
412 }
413
414
415 public void setIncludes( String[] includes )
416 {
417 if ( includes == null )
418 {
419 // We should not include non-java files, so we use a sensible default pattern
420 this.includes = DEFAULT_INCLUDES;
421 }
422 else
423 {
424 this.includes = includes;
425 }
426 }
427 }