View Javadoc
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 1544863 2013-11-23 18:54:06Z michaelo $
40   */
41  public class JXR
42  {
43      /**
44       * The Log.
45       */
46      private Log log;
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 String dest = "";
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 String javadocLinkDir;
68  
69      /**
70       * Handles taking .java files and changing them into html. "More than meets
71       * the eye!" :)
72       */
73      private JavaCodeTransform transformer;
74  
75      /**
76       * The revision of the module currently being processed.
77       */
78      private String revision;
79  
80      /**
81       * The list of exclude patterns to use.
82       */
83      private String[] excludes = null;
84  
85      /**
86       * The list of include patterns to use.
87       */
88      private String[] includes = DEFAULT_INCLUDES;
89  
90      /**
91       * Now that we have instantiated everything. Process this JXR task.
92       *
93       * @param packageManager
94       * @param source
95       * @param bottom
96       * @throws IOException
97       */
98      public void processPath( PackageManager packageManager, String source, String bottom )
99          throws IOException
100     {
101         this.transformer = new JavaCodeTransform( packageManager );
102 
103         DirectoryScanner ds = new DirectoryScanner();
104         // I'm not sure why we don't use the directoryScanner in packageManager,
105         // but since we don't we need to set includes/excludes here as well
106         ds.setExcludes( excludes );
107         ds.setIncludes( includes );
108         ds.addDefaultExcludes();
109 
110         File dir = new File( source );
111 
112         if ( !dir.exists() )
113         {
114             if ( !dir.mkdirs() )
115             {
116                 throw new IllegalStateException(
117                     "Your source directory does not exist and could not be created:" + source );
118             }
119         }
120 
121         ds.setBasedir( source );
122         ds.scan();
123 
124         //now get the list of included files
125 
126         String[] files = ds.getIncludedFiles();
127 
128         for ( int i = 0; i < files.length; ++i )
129         {
130             String src = source + System.getProperty( "file.separator" ) + files[i];
131 
132             if ( isJavaFile( src ) )
133             {
134                 transform( src, getDestination( source, src ), bottom );
135             }
136 
137         }
138     }
139 
140     /**
141      * Check to see if the file is a Java source file.
142      *
143      * @param filename The name of the file to check
144      * @return <code>true</true> if the file is a Java file
145      */
146     public static boolean isJavaFile( String filename )
147     {
148         File file = new File( filename );
149         return filename.endsWith( ".java" ) && file.length() > 0;
150     }
151 
152     /**
153      * Check to see if the file is an HTML file.
154      *
155      * @param filename The name of the file to check
156      * @return <code>true</true> if the file is an HTML file
157      */
158     public static boolean isHtmlFile( String filename )
159     {
160         return filename.endsWith( ".html" );
161     }
162 
163     /**
164      * Get the path to the destination files.
165      *
166      * @return The path to the destination files
167      */
168     public String getDest()
169     {
170         return this.dest;
171     }
172 
173     /**
174      * @param dest
175      */
176     public void setDest( String dest )
177     {
178         this.dest = dest;
179     }
180 
181     /**
182      * @param locale
183      */
184     public void setLocale( Locale locale )
185     {
186         this.locale = locale;
187     }
188 
189     /**
190      * @param inputEncoding
191      */
192     public void setInputEncoding( String inputEncoding )
193     {
194         this.inputEncoding = inputEncoding;
195     }
196 
197     /**
198      * @param outputEncoding
199      */
200     public void setOutputEncoding( String outputEncoding )
201     {
202         this.outputEncoding = outputEncoding;
203     }
204 
205     /**
206      * @param javadocLinkDir
207      */
208     public void setJavadocLinkDir( String javadocLinkDir )
209     {
210         // get a relative link to the javadocs
211         this.javadocLinkDir = javadocLinkDir;
212     }
213 
214     /**
215      * @param transformer
216      */
217     public void setTransformer( JavaCodeTransform transformer )
218     {
219         this.transformer = transformer;
220     }
221 
222     /**
223      * @param revision
224      */
225     public void setRevision( String revision )
226     {
227         this.revision = revision;
228     }
229 
230     /**
231      * @param log
232      */
233     public void setLog( Log log )
234     {
235         this.log = log;
236     }
237 
238     /**
239      * @param sourceDirs
240      * @param templateDir
241      * @param windowTitle
242      * @param docTitle
243      * @param bottom
244      * @throws IOException
245      * @throws JxrException
246      */
247     public void xref( List sourceDirs, String templateDir, String windowTitle, String docTitle, String bottom )
248         throws IOException, JxrException
249     {
250         // first collect package and class info
251         FileManager fileManager = new FileManager();
252         fileManager.setEncoding( inputEncoding );
253 
254         PackageManager pkgmgr = new PackageManager( log, fileManager );
255         pkgmgr.setExcludes( excludes );
256         pkgmgr.setIncludes( includes );
257 
258         // go through each source directory and xref the java files
259         for ( Iterator i = sourceDirs.iterator(); i.hasNext(); )
260         {
261             String path = (String) i.next();
262             path = new File( path ).getCanonicalPath();
263 
264             pkgmgr.process( path );
265 
266             processPath( pkgmgr, path, bottom );
267         }
268 
269         // once we have all the source files xref'd, create the index pages
270         DirectoryIndexer indexer = new DirectoryIndexer( pkgmgr, dest );
271         indexer.setOutputEncoding( outputEncoding );
272         indexer.setTemplateDir( templateDir );
273         indexer.setWindowTitle( windowTitle );
274         indexer.setDocTitle( docTitle );
275         indexer.setBottom( bottom );
276         indexer.process( log );
277     }
278 
279     // ----------------------------------------------------------------------
280     // private methods
281     // ----------------------------------------------------------------------
282 
283     /**
284      * Given a filename get the destination on the filesystem of where to store
285      * the to be generated HTML file. Pay attention to the package name.
286      *
287      * @param source
288      * @param filename
289      * @return A String with the store destination.
290      */
291     private String getDestination( String source, String filename )
292     {
293         //remove the source directory from the filename.
294 
295         String dest = filename.substring( source.length(), filename.length() );
296 
297         int start = 0;
298         int end = dest.indexOf( ".java" );
299 
300         if ( end != -1 )
301         {
302             //remove the .java from the filename
303             dest = dest.substring( start, end );
304         }
305 
306         //add the destination directory to the filename.
307         dest = this.getDest() + dest;
308 
309         //add .html to the filename
310 
311         dest = dest + ".html";
312 
313         return dest;
314     }
315 
316     /**
317      * Given a source file transform it into HTML and write it to the
318      * destination (dest) file.
319      *
320      * @param source The java source file
321      * @param dest The directory to put the HTML into
322      * @param bottom The bottom footer text just as in the package pages
323      * @throws IOException Thrown if the transform can't happen for some reason.
324      */
325     private void transform( String source, String dest, String bottom )
326         throws IOException
327     {
328         log.debug( source + " -> " + dest );
329 
330         // get a relative link to the javadocs
331         String javadoc = javadocLinkDir != null ? getRelativeLink( dest, javadocLinkDir ) : null;
332         transformer.transform( source, dest, locale, inputEncoding, outputEncoding, javadoc,
333             this.revision, bottom );
334     }
335 
336     /**
337      * Creates a relative link from one directory to another.
338      *
339      * Example:
340      * given <code>/foo/bar/baz/oink</code>
341      * and <code>/foo/bar/schmoo</code>
342      *
343      * this method will return a string of <code>"../../schmoo/"</code>
344      *
345      * @param fromDir The directory from which the link is relative.
346      * @param toDir The directory into which the link points.
347      * @return a String of format <code>"../../schmoo/"</code>
348      * @throws java.io.IOException If a problem is encountered while navigating through the directories.
349      */
350     private static String getRelativeLink( String fromDir, String toDir )
351         throws IOException
352     {
353         StringBuffer toLink = new StringBuffer();   // up from fromDir
354         StringBuffer fromLink = new StringBuffer(); // down into toDir
355 
356         // create a List of toDir's parent directories
357         List parents = new LinkedList();
358         File f = new File( toDir );
359         f = f.getCanonicalFile();
360         while ( f != null )
361         {
362             parents.add( f );
363             f = f.getParentFile();
364         }
365 
366         // walk up fromDir to find the common parent
367         f = new File( fromDir );
368         if ( !f.isDirectory() )
369         {
370             // Passed in a fromDir with a filename on the end - strip it
371             f = f.getParentFile();
372         }
373         f = f.getCanonicalFile();
374         f = f.getParentFile();
375         boolean found = false;
376         while ( f != null && !found )
377         {
378             for ( int i = 0; i < parents.size(); ++i )
379             {
380                 File parent = (File) parents.get( i );
381                 if ( f.equals( parent ) )
382                 {
383                     // when we find the common parent, add the subdirectories
384                     // down to toDir itself
385                     for ( int j = 0; j < i; ++j )
386                     {
387                         File p = (File) parents.get( j );
388                         toLink.insert( 0, p.getName() + "/" );
389                     }
390                     found = true;
391                     break;
392                 }
393             }
394             f = f.getParentFile();
395             fromLink.append( "../" );
396         }
397 
398         if ( !found )
399         {
400             throw new FileNotFoundException( fromDir + " and " + toDir + " have no common parent." );
401         }
402 
403         return fromLink.append( toLink.toString() ).toString();
404     }
405 
406     public void setExcludes( String[] excludes )
407     {
408         this.excludes = excludes;
409     }
410 
411 
412     public void setIncludes( String[] includes )
413     {
414         if ( includes == null )
415         {
416             // We should not include non-java files, so we use a sensible default pattern
417             this.includes = DEFAULT_INCLUDES;
418         }
419         else
420         {
421             this.includes = includes;
422         }
423     }
424 }