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