blob: f385ec0ef7ad4b792a89d0ac1f8db481c9c12356 [file] [log] [blame]
package org.apache.maven.jxr;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.jxr.ant.DirectoryScanner;
import org.apache.maven.jxr.log.Log;
import org.apache.maven.jxr.pacman.FileManager;
import org.apache.maven.jxr.pacman.PackageManager;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
/**
* Main entry point into Maven used to kick off the XReference code building.
*
* @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
* @version $Id$
*/
public class JXR
{
/**
* The Log.
*/
private Log log;
/**
* Description of the Notice.
*/
public static final String NOTICE = "This page was automatically generated by " +
"<a href=\"http://maven.apache.org/\">Maven</a>";
/**
* The default list of include patterns to use.
*/
private static final String[] DEFAULT_INCLUDES = {"**/*.java"};
/**
* Path to destination.
*/
private String dest = "";
private Locale locale;
private String inputEncoding;
private String outputEncoding;
/**
* Relative path to javadocs, suitable for hyperlinking.
*/
private String javadocLinkDir;
/**
* Handles taking .java files and changing them into html. "More than meets
* the eye!" :)
*/
private JavaCodeTransform transformer;
/**
* The revision of the module currently being processed.
*/
private String revision;
/**
* The list of exclude patterns to use.
*/
private String[] excludes = null;
/**
* The list of include patterns to use.
*/
private String[] includes = DEFAULT_INCLUDES;
/**
* Now that we have instantiated everything. Process this JXR task.
*
* @param packageManager
* @param source
* @throws IOException
*/
public void processPath( PackageManager packageManager, String source )
throws IOException
{
this.transformer = new JavaCodeTransform( packageManager );
DirectoryScanner ds = new DirectoryScanner();
// I'm not sure why we don't use the directoryScanner in packageManager,
// but since we don't we need to set includes/excludes here as well
ds.setExcludes( excludes );
ds.setIncludes( includes );
ds.addDefaultExcludes();
File dir = new File( source );
if ( !dir.exists() )
{
if ( !dir.mkdirs() )
{
throw new IllegalStateException(
"Your source directory does not exist and could not be created:" + source );
}
}
ds.setBasedir( source );
ds.scan();
//now get the list of included files
String[] files = ds.getIncludedFiles();
for ( int i = 0; i < files.length; ++i )
{
String src = source + System.getProperty( "file.separator" ) + files[i];
if ( isJavaFile( src ) )
{
transform( src, getDestination( source, src ) );
}
}
}
/**
* Check to see if the file is a Java source file.
*
* @param filename The name of the file to check
* @return <code>true</true> if the file is a Java file
*/
public static boolean isJavaFile( String filename )
{
File file = new File( filename );
return filename.endsWith( ".java" ) && file.length() > 0;
}
/**
* Check to see if the file is an HTML file.
*
* @param filename The name of the file to check
* @return <code>true</true> if the file is an HTML file
*/
public static boolean isHtmlFile( String filename )
{
return filename.endsWith( ".html" );
}
/**
* Get the path to the destination files.
*
* @return The path to the destination files
*/
public String getDest()
{
return this.dest;
}
/**
* @param dest
*/
public void setDest( String dest )
{
this.dest = dest;
}
/**
* @param locale
*/
public void setLocale( Locale locale )
{
this.locale = locale;
}
/**
* @param inputEncoding
*/
public void setInputEncoding( String inputEncoding )
{
this.inputEncoding = inputEncoding;
}
/**
* @param outputEncoding
*/
public void setOutputEncoding( String outputEncoding )
{
this.outputEncoding = outputEncoding;
}
/**
* @param javadocLinkDir
*/
public void setJavadocLinkDir( String javadocLinkDir )
{
// get a relative link to the javadocs
this.javadocLinkDir = javadocLinkDir;
}
/**
* @param transformer
*/
public void setTransformer( JavaCodeTransform transformer )
{
this.transformer = transformer;
}
/**
* @param revision
*/
public void setRevision( String revision )
{
this.revision = revision;
}
/**
* @param log
*/
public void setLog( Log log )
{
this.log = log;
}
/**
* @param sourceDirs
* @param templateDir
* @param windowTitle
* @param docTitle
* @param bottom
* @throws IOException
* @throws JxrException
*/
public void xref( List sourceDirs, String templateDir, String windowTitle, String docTitle, String bottom )
throws IOException, JxrException
{
// first collect package and class info
FileManager fileManager = new FileManager();
fileManager.setEncoding( inputEncoding );
PackageManager pkgmgr = new PackageManager( log, fileManager );
pkgmgr.setExcludes( excludes );
pkgmgr.setIncludes( includes );
// go through each source directory and xref the java files
for ( Iterator i = sourceDirs.iterator(); i.hasNext(); )
{
String path = (String) i.next();
path = new File( path ).getCanonicalPath();
pkgmgr.process( path );
processPath( pkgmgr, path );
}
// once we have all the source files xref'd, create the index pages
DirectoryIndexer indexer = new DirectoryIndexer( pkgmgr, dest );
indexer.setOutputEncoding( outputEncoding );
indexer.setTemplateDir( templateDir );
indexer.setWindowTitle( windowTitle );
indexer.setDocTitle( docTitle );
indexer.setBottom( bottom );
indexer.process( log );
}
// ----------------------------------------------------------------------
// private methods
// ----------------------------------------------------------------------
/**
* Given a filename get the destination on the filesystem of where to store
* the to be generated HTML file. Pay attention to the package name.
*
* @param source
* @param filename
* @return A String with the store destination.
*/
private String getDestination( String source, String filename )
{
//remove the source directory from the filename.
String dest = filename.substring( source.length(), filename.length() );
int start = 0;
int end = dest.indexOf( ".java" );
if ( end != -1 )
{
//remove the .java from the filename
dest = dest.substring( start, end );
}
//add the destination directory to the filename.
dest = this.getDest() + dest;
//add .html to the filename
dest = dest + ".html";
return dest;
}
/**
* Given a source file transform it into HTML and write it to the
* destination (dest) file.
*
* @param source The jave source file
* @param dest The directory to put the HTML into
* @throws IOException Thrown if the transform can't happen for some reason.
*/
private void transform( String source, String dest )
throws IOException
{
log.debug( source + " -> " + dest );
// get a relative link to the javadocs
String javadoc = javadocLinkDir != null ? getRelativeLink( dest, javadocLinkDir ) : null;
transformer.transform( source, dest, locale, inputEncoding, outputEncoding, javadoc, this.revision );
}
/**
* Creates a relative link from one directory to another.
*
* Example:
* given /foo/bar/baz/oink
* and /foo/bar/schmoo
*
* this method will return a string of "../../schmoo/"
*
* @param fromDir The directory from which the link is relative.
* @param toDir The directory into which the link points.
* @return a string of format "../../schmoo/"
* @throws java.io.IOException If a problem is encountered while navigating through the directories.
*/
private static String getRelativeLink( String fromDir, String toDir )
throws IOException
{
StringBuffer toLink = new StringBuffer(); // up from fromDir
StringBuffer fromLink = new StringBuffer(); // down into toDir
// create a List of toDir's parent directories
List parents = new LinkedList();
File f = new File( toDir );
f = f.getCanonicalFile();
while ( f != null )
{
parents.add( f );
f = f.getParentFile();
}
// walk up fromDir to find the common parent
f = new File( fromDir );
if ( !f.isDirectory() ) {
// Passed in a fromDir with a filename on the end - strip it
f = f.getParentFile();
}
f = f.getCanonicalFile();
f = f.getParentFile();
boolean found = false;
while ( f != null && !found )
{
for ( int i = 0; i < parents.size(); ++i )
{
File parent = (File) parents.get( i );
if ( f.equals( parent ) )
{
// when we find the common parent, add the subdirectories
// down to toDir itself
for ( int j = 0; j < i; ++j )
{
File p = (File) parents.get( j );
toLink.insert( 0, p.getName() + "/" );
}
found = true;
break;
}
}
f = f.getParentFile();
fromLink.append( "../" );
}
if ( !found )
{
throw new FileNotFoundException( fromDir + " and " + toDir + " have no common parent." );
}
return fromLink.append( toLink.toString() ).toString();
}
public void setExcludes( String[] excludes )
{
this.excludes = excludes;
}
public void setIncludes( String[] includes )
{
if ( includes == null )
{
// We should not include non-java files, so we use a sensible default pattern
this.includes = DEFAULT_INCLUDES;
}
else
{
this.includes = includes;
}
}
}