blob: 3fa68391e141aae6f7128888569ec124580499b9 [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.pacman.ClassType;
import org.apache.maven.jxr.pacman.PackageManager;
import org.apache.maven.jxr.pacman.PackageType;
import org.apache.maven.jxr.log.VelocityLogger;
import org.apache.maven.jxr.log.Log;
import org.apache.oro.text.perl.Perl5Util;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.codehaus.plexus.util.IOUtil;
import java.io.File;
import java.io.FileWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
/**
* This class creates the navigational pages for jxr's cross-referenced source
* files. The navigation is inspired by javadoc, so it should have a familiar feel.
*
* Creates the following files:
* <ul>
* <li>index.html main index containing the frameset</li>
* <li>overview-frame.html list of the project's packages (top left)</li>
* <li>allclasses-frame.html list of all classes in the project (bottom left)</li>
* <li>overview-summary.html top-level listing of the project's packages (main frame)</li>
*
* <ul>
* Package specific:
* <li>package-summary.html listing of all classes in this package (main frame)</li>
* <li>package-frame.html listing of all classes in this package (bottom left)</li>
* </ul>
* </ul>
*
* @author <a href="mailto:bellingard@gmail.com">Fabrice Bellingard </a>
* @author <a href="mailto:brian@brainslug.org">Brian Leonard</a>
* @version $Id$
*/
public class DirectoryIndexer
{
/*
* JavaCodeTransform uses this to cross-reference package references
* with that package's main summary page.
*/
final static String INDEX = "package-summary.html";
/*
* Path to the root output directory.
*/
private String root;
/*
* Package Manager for this project.
*/
private PackageManager packageManager;
/*
* see the getter/setter docs for these properties
*/
private String outputEncoding;
private String templateDir;
private String windowTitle;
private String docTitle;
private String bottom;
/**
* Constructor for the DirectoryIndexer object
*
* @param packageManager PackageManager for this project
* @param root Path of the root output directory
*/
public DirectoryIndexer( PackageManager packageManager, String root )
{
this.packageManager = packageManager;
this.root = root;
}
/**
* OutputEncoding is the encoding of output files.
*
* @param outputEncoding output Encoding
*/
public void setOutputEncoding( String outputEncoding )
{
this.outputEncoding = outputEncoding;
}
/**
* see setOutputEncoding(String)
*/
public String getOutputEncoding()
{
return outputEncoding;
}
/**
* TemplateDir is the location of the jelly template files used
* to generate the navigation pages.
*
* @param templateDir location of the template directory
*/
public void setTemplateDir( String templateDir )
{
this.templateDir = templateDir;
}
/**
* see setTemplateDir(String)
*/
public String getTemplateDir()
{
return templateDir;
}
/**
* WindowTitle is used in the output's &lt;title&gt; tags
* see the javadoc documentation for the property of the same name
*
* @param windowTitle the &lt;title&gt; attribute
*/
public void setWindowTitle( String windowTitle )
{
this.windowTitle = windowTitle;
}
/**
* see setWindowTitle(String)
*
* @see #setWindowTitle(String) setWindowTitle
*/
public String getWindowTitle()
{
return windowTitle;
}
/**
* DocTitle is used as a page heading for the summary files
* see the javadoc documentation for the property of the same name
*
* @param docTitle major page heading
*/
public void setDocTitle( String docTitle )
{
this.docTitle = docTitle;
}
/**
* see setDocTitle(String)
*
* @see #setDocTitle(String) setDocTitle
*/
public String getDocTitle()
{
return docTitle;
}
/**
* Bottom is a footer for the navigation pages, usually a copyright
* see the javadoc documentation for the property of the same name
*
* @param bottom page footer
*/
public void setBottom( String bottom )
{
this.bottom = bottom;
}
/**
* see setBottom(String)
*
* @see #setBottom(String) setBottom
*/
public String getBottom()
{
return bottom;
}
/**
* Does the actual indexing.
*
* @throws JxrException If something went wrong
*/
public void process( Log log )
throws JxrException
{
Map info = getPackageInfo();
VelocityEngine engine = new VelocityEngine();
setProperties( engine, log );
try
{
engine.init();
}
catch ( Exception e )
{
throw new JxrException( "Error initialising Velocity", e );
}
VelocityContext context = new VelocityContext();
context.put( "outputEncoding", getOutputEncoding() );
context.put( "windowTitle", getWindowTitle() );
context.put( "docTitle", getDocTitle() );
context.put( "bottom", getBottom() );
context.put( "info", info );
doVelocity( "index", root, context, engine );
doVelocity( "overview-frame", root, context, engine );
doVelocity( "allclasses-frame", root, context, engine );
doVelocity( "overview-summary", root, context, engine );
Iterator iter = ( (Map) info.get( "allPackages" ) ).values().iterator();
while ( iter.hasNext() )
{
Map pkgInfo = (Map) iter.next();
VelocityContext subContext = new VelocityContext( context );
subContext.put( "pkgInfo", pkgInfo );
String outDir = root + "/" + (String) pkgInfo.get( "dir" );
doVelocity( "package-summary", outDir, subContext, engine );
doVelocity( "package-frame", outDir, subContext, engine );
}
}
/*
* Set Velocity properties to find templates
*/
private void setProperties( VelocityEngine engine, Log log )
{
File templateDirFile = new File( getTemplateDir() );
if ( templateDirFile.isAbsolute() )
{
// the property has been overriden: need to use a FileResourceLoader
engine.setProperty( "resource.loader", "file" );
engine.setProperty( "file.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.FileResourceLoader" );
engine.setProperty( "file.resource.loader.path", templateDirFile.toString() );
}
else
{
// use of the default templates
engine.setProperty( "resource.loader", "classpath" );
engine.setProperty( "classpath.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" );
}
// avoid "unable to find resource 'VM_global_library.vm' in any resource loader."
engine.setProperty( "velocimacro.library", "" );
engine.setProperty( Log.class.getName(), log );
engine.setProperty( "runtime.log.logsystem.class", VelocityLogger.class.getName() );
}
/*
* Generate the HTML file according to the Velocity template
*/
private void doVelocity( String templateName, String outDir, VelocityContext context, VelocityEngine engine )
throws JxrException
{
// output file
File file = new File( outDir, templateName + ".html" );
file.getParentFile().mkdirs();
FileWriter writer = null;
try
{
writer = new FileWriter( file );
// template file
StringBuffer templateFile = new StringBuffer();
File templateDirFile = new File( getTemplateDir() );
if ( !templateDirFile.isAbsolute() )
{
// default templates
templateFile.append( getTemplateDir() );
templateFile.append( "/" );
}
templateFile.append( templateName );
templateFile.append( ".vm" );
Template template = engine.getTemplate( templateFile.toString() );
// do the merge
template.merge( context, writer );
writer.flush();
}
catch ( Exception e )
{
throw new JxrException( "Error merging velocity template", e );
}
finally
{
IOUtil.close( writer );
}
}
/*
* Creates a Map of other Maps containing information about
* this project's packages and classes, obtained from the PackageManager.
*
* allPackages collection of Maps with package info, with the following format
* {name} package name (e.g., "org.apache.maven.jxr")
* {dir} package dir relative to the root output dir (e.g., "org/apache/maven/jxr")
* {rootRef} relative link to root output dir (e.g., "../../../../") note trailing slash
* {classes} collection of Maps with class info
* {name} class name (e.g., "DirectoryIndexer")
* {dir} duplicate of package {dir}
*
* allClasses collection of Maps with class info, format as above
*
*/
private Map getPackageInfo()
{
TreeMap allPackages = new TreeMap();
TreeMap allClasses = new TreeMap();
Perl5Util perl = new Perl5Util();
Enumeration packages = packageManager.getPackageTypes();
while ( packages.hasMoreElements() )
{
PackageType pkg = (PackageType) packages.nextElement();
String pkgName = pkg.getName();
String pkgDir = perl.substitute( "s/\\./\\//g", pkgName );
String rootRef = perl.substitute( "s/[^\\.]*(\\.|$)/..\\//g", pkgName );
// special case for the default package
// javadoc doesn't deal with it, but it's easy for us
if ( pkgName.length() == 0 )
{
pkgName = "(default package)";
pkgDir = ".";
rootRef = "./";
}
TreeMap pkgClasses = new TreeMap();
Enumeration classes = pkg.getClassTypes();
while ( classes.hasMoreElements() )
{
ClassType clazz = (ClassType) classes.nextElement();
String className = clazz.getName();
Map classInfo = new HashMap();
if( clazz.getFilename() != null )
{
classInfo.put( "filename", clazz.getFilename() );
}
else {
classInfo.put( "filename", "" );
}
classInfo.put( "name", className );
classInfo.put( "dir", pkgDir );
pkgClasses.put( className, classInfo );
allClasses.put( className, classInfo );
}
Map pkgInfo = new HashMap();
pkgInfo.put( "name", pkgName );
pkgInfo.put( "dir", pkgDir );
pkgInfo.put( "classes", pkgClasses );
pkgInfo.put( "rootRef", rootRef );
allPackages.put( pkgName, pkgInfo );
}
Map info = new HashMap();
info.put( "allPackages", allPackages );
info.put( "allClasses", allClasses );
return info;
}
}