blob: 8e7489cc9d1cd978e41496be6f10f47f74a12039 [file] [log] [blame]
/*
* 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.
*/
package org.apache.myfaces.plugins.jsdoc;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.xml.stream.XMLStreamException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.MavenReportException;
import org.apache.myfaces.plugins.jsdoc.util.HTMLFileContentFilter;
import org.apache.myfaces.plugins.jsdoc.util.JSDocPackMaven;
import org.apache.myfaces.plugins.jsdoc.util.JSFileNameFilter;
import org.apache.myfaces.plugins.jsdoc.util.XMLConfig;
public abstract class AbstractJSDocMojo extends AbstractMojo
{
// ----------------------------------------------------------------------
// Mojo components
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// Mojo parameters
// ----------------------------------------------------------------------
/**
* The Maven Project Object
*
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
/**
* the root project build dir (target directory)
*
* @parameter expression="${project.build.directory}"
*/
protected String projectBuildDir;
// ----------------------------------------------------------------------
// Standard Options
// ----------------------------------------------------------------------
/**
* The project source javascript directory, which are the source
* files unprocessed by myfaces javascript plugin
*
* @parameter expression="${basedir}/src/main/javascript/"
*/
protected String sourceDirectory;
/**
* The relative dir name sourceDirectory is
*
* @parameter expression="src/main/javascript/"
*/
protected String relativeSourceDirectory;
/**
* The project resource directory, to take all files ending
* with .js
*
* @parameter expression="${basedir}/src/main/resources/"
*/
protected File resourceDirectory;
/**
* The relative dir name resourceDirectory is
*
* @parameter expression="src/main/resources/"
*/
protected String relativeResourceDirectory;
/**
* The project webapp directory, to take all files ending
* with .js
*
* @parameter expression="${basedir}/src/main/webapp/"
*/
protected String webappDirectory;
/**
* The relative dir name webappDirectory is
*
* @parameter expression="src/main/webapp/"
*/
protected String relativeWebappDirectory;
/**
* Specifies the destination directory where jsdoc saves the generated HTML files.
*
* @parameter expression="${destDir}" alias="destDir" default-value="${project.build.directory}/jsdoc"
* @required
*/
protected File outputDirectory;
/**
* Path to the assembly file containing the file paths to our source javascript files
*
* @parameter expression="${basedir}/src/assembler/jsdoc-compiler.xml"
*/
protected String assemblyFile;
/**
* Specifies whether the Javadoc generation should be skipped.
*
* @since 2.5
* @parameter expression="${myfaces.jsdoc.skip}" default-value="false"
*/
protected boolean skip;
// ----------------------------------------------------------------------
// Standard JSDoc Options
// ----------------------------------------------------------------------
//various jsdoc params, copied over as well as the corresponding snippets from
/**
* Whether to include symbols tagged as private. Default is <code>false</code>.
*
* @parameter expression="false"
*/
protected boolean includePrivate;
/**
* Include all functions, even undocumented ones. Default is <code>false</code>.
*
* @parameter expression="false"
*/
protected boolean includeUndocumented;
/**
* Include all functions, even undocumented, underscored ones. Default is <code>false</code>.
*
* @parameter expression="false"
*/
protected boolean includeUndocumentedUnderscored;
/**
* template directory used by jsdoc the default is <code>templates/jsdoc</code> under the jsdoc root
*
* @parameter expression="templates/jsdoc"
*/
protected String templates;
// ----------------------------------------------------------------------
// protected methods
// ----------------------------------------------------------------------
protected void executeReport( Locale unusedLocale )
throws MavenReportException
{
JSDocHelper helper = _setup();
try
{
_execute(helper);
}
catch (IOException e)
{
throw new MavenReportException(e.toString());
}
finally
{
_tearDown(helper);
}
}
/**
* @return the output directory
*/
protected String getOutputDirectory()
{
return outputDirectory.getAbsoluteFile().toString();
}
protected MavenProject getProject()
{
return project;
}
// ----------------------------------------------------------------------
// private methods
// ----------------------------------------------------------------------
protected JSDocHelper _setup() throws MavenReportException
{
JSDocHelper helper = new JSDocHelper();
try
{
if (new File(assemblyFile).exists())
{
helper.setFileMap(new XMLConfig(assemblyFile));
}
}
catch (XMLStreamException e)
{
getLog().error(e);
throw new MavenReportException(e.toString());
}
catch (FileNotFoundException e)
{
getLog().error(e);
throw new MavenReportException(e.toString());
}
helper.setUnpacker(new JSDocPackMaven());
//unpacker = new JSDocPackResources();
helper.setJsdocRunPath(projectBuildDir + File.separator + JSDocMojoConst.JSDOC);
helper.setJsdocEngineUnpacked(projectBuildDir + File.separator + JSDocMojoConst.TEMP
+ File.separator + JSDocMojoConst.JSDOC);
helper.setJavascriptTargetPath(helper.getJsdocRunPath() + File.separator + JSDocMojoConst.JAVASCRIPT);
File pathCreator = new File(helper.getJsdocEngineUnpacked());
File jsdocPathCreator = new File(helper.getJavascriptTargetPath());
pathCreator.mkdirs();
jsdocPathCreator.mkdirs();
return helper;
}
public void _tearDown(JSDocHelper helper) throws MavenReportException
{
try
{
FileUtils.deleteDirectory(new File(helper.getJsdocEngineUnpacked()));
}
catch (IOException e)
{
throw new MavenReportException(e.toString());
}
}
protected void _execute(JSDocHelper helper) throws MavenReportException, IOException
{
copyJavascripts(helper);
//fetchJavascriptSources(helper);
//now we have all files we now can now work on our plugin call
unpackJSDoc(helper);
String systemJsdocDir = setenvJSDocDir(helper);
String userDir = setenvUserDir(helper);
try
{
executeJSDoc(helper);
}
finally
{
resetSysenvVars(systemJsdocDir, userDir);
}
}
private void resetSysenvVars(String systemJsdocDir, String userDir)
{
if (systemJsdocDir != null)
{
System.setProperty(JSDocMojoConst.JSDOC_DIR, systemJsdocDir);
}
if (userDir != null)
{
System.setProperty("user.dir", userDir);
}
}
private void executeJSDoc(JSDocHelper helper)
{
List args = _initArguments(helper);
getLog().info("[JSDOC] Executing within maven: '" + args.toString().replaceAll(",", "") + "'");
// tell Rhino to run JSDoc with the provided params
// without calling System.exit
org.mozilla.javascript.tools.shell.Main.main((String[]) args.toArray(new String[0]));
this.fixHTML(helper);
}
private String setenvUserDir(JSDocHelper helper)
{
String userDir = System.getProperty("user.dir");
System.setProperty("user.dir", helper.getJsdocEngineUnpacked() + File.separator);
return userDir;
}
private String setenvJSDocDir(JSDocHelper helper)
{
String systemJsdocDir = System.getProperty(JSDocMojoConst.JSDOC_DIR);
System.setProperty(JSDocMojoConst.JSDOC_DIR, helper.getJsdocEngineUnpacked() + File.separator);
return systemJsdocDir;
}
private void unpackJSDoc(JSDocHelper helper) throws IOException
{
getLog().info("[JSDOC] Unpacking jsdoc toolkit for further processing");
helper.getUnpacker().unpack(helper.getJsdocEngineUnpacked(), getLog());
getLog().info("[JSDOC] Unpacking jsdoc toolkit for further processing done");
}
/**
* initially copies all source files from the given source dir to the target
* dir so that the files can be referenced later on by the html files
*/
private void copyJavascripts(JSDocHelper helper) throws IOException
{
getLog().info("[JSDOC] Copying all javascript sources to the target dir for later reference");
if (!StringUtils.isEmpty(sourceDirectory))
{
File buildSourceDirFile = new File(sourceDirectory);
if (buildSourceDirFile.exists())
{
FileUtils.copyDirectory(
buildSourceDirFile,
new File(helper.getJavascriptTargetPath()+'/'+relativeSourceDirectory),
new FileFilter()
{
public boolean accept(File pathname)
{
if (pathname.getName().endsWith(".svn"))
{
return false;
}
return true;
}
});
}
}
if (resourceDirectory != null)
{
if (resourceDirectory.exists())
{
FileUtils.copyDirectory(
resourceDirectory,
new File(helper.getJavascriptTargetPath()+'/'+relativeResourceDirectory),
new FileFilter()
{
public boolean accept(File pathname)
{
if (pathname.getName().endsWith(".svn"))
{
return false;
}
if (pathname.isDirectory())
{
return true;
}
if (pathname.getName().endsWith(".js"))
{
return true;
}
return false;
}
});
}
}
if (!StringUtils.isEmpty(webappDirectory))
{
File buildWebappSourceDirFile = new File(webappDirectory);
if (buildWebappSourceDirFile.exists())
{
FileUtils.copyDirectory(
buildWebappSourceDirFile,
new File(helper.getJavascriptTargetPath()+'/'+relativeWebappDirectory),
new FileFilter()
{
public boolean accept(File pathname)
{
if (pathname.getName().endsWith(".svn"))
{
return false;
}
if (pathname.isDirectory())
{
return true;
}
if (pathname.getName().endsWith(".js"))
{
return true;
}
return false;
}
});
}
}
getLog().info("[JSDOC] Copying done without any errors");
}
private final List _initArguments(JSDocHelper helper)
{
List args = new ArrayList();
String runJsPath = helper.getJsdocEngineUnpacked() + File.separator + JSDocMojoConst.APP
+ File.separator + JSDocMojoConst.RUN_JS;
args.add(runJsPath);
if (this.includeUndocumented)
{
args.add(JSDocMojoConst.PARAM_UNDOCUMENTED);
}
if (this.includeUndocumentedUnderscored)
{
args.add(JSDocMojoConst.PARAM_UNDOCUMENTED_UNDERSCORED);
}
if (this.includePrivate)
{
args.add(JSDocMojoConst.PARAM_PRIVATE);
}
args.add(JSDocMojoConst.PARAM_OUTPUT + JSDocMojoConst.EQUALS + this.getOutputDirectory());
args.add(JSDocMojoConst.PARAM_TEMPLATE + JSDocMojoConst.EQUALS + getTemplateDirectory(helper));
args.addAll(fetchJavascriptSources(helper));
//according to the run.js source the last argument
//must be a -j param pointing to the jsdoc javascripts
args.add(JSDocMojoConst.PARAM_JS_FLAG + JSDocMojoConst.EQUALS + runJsPath);
return args;
}
/**
* @return the directory as absolute path holding the jsdoc toolkit templates
*/
private final String getTemplateDirectory(JSDocHelper helper)
{
return (JSDocMojoConst.TEMPLATES_JSDOC.equals(this.templates)) ?
helper.getJsdocEngineUnpacked() + File.separator + this.templates :
this.templates;
}
/**
* @return the target directory for the jsdoc files
*/
/*
private final String getOutputDirectory()
{
return (this.outputDirectory == null || this.outputDirectory.equals("")) ?
projectBuildDir + File.separator + JSDocMojoConst.JSDOC :
this.outputDirectory;
}*/
/**
* @return fetches the sources for the javascripts in the order given by the xml
*/
private List<String> fetchJavascriptSources(JSDocHelper helper)
{
List<String> sources = null;
getLog().info("[JSDOC] Fetch Javascript sources for further processing");
if (helper.getFileMap() == null)
{
sources = new ArrayList<String>();
File javascriptTargetFileBase = new File(helper.getJavascriptTargetPath());
addSources(sources, javascriptTargetFileBase);
return sources;
}
else
{
JSFileNameFilter fileNameFilter = new JSFileNameFilter(helper.getFileMap());
//FileUtils.iterateFiles(new File(getOutputDirectory()), fileNameFilter, TrueFileFilter.INSTANCE);
FileUtils.iterateFiles(new File(helper.getJavascriptTargetPath()), fileNameFilter, TrueFileFilter.INSTANCE);
Map sortedResult = fileNameFilter.getSortedResults();
sources = new ArrayList(sortedResult.size());
Iterator it = sortedResult.entrySet().iterator();
while (it.hasNext())
{
Map.Entry singleItem = (Map.Entry) it.next();
String finalFileName = (String) singleItem.getValue();
sources.add(finalFileName);
}
}
getLog().info("[JSDOC] All Javascript sources are prepared for processing");
return sources;
}
private void addSources(List<String> sources, File file)
{
if (file.isDirectory())
{
File[] files = file.listFiles();
if (files != null)
{
for (int i = 0; i < files.length; i++)
{
addSources(sources, files[i]);
}
}
}
else
{
sources.add(file.getAbsolutePath());
}
}
private void fixHTML(JSDocHelper helper)
{
FileUtils.iterateFiles(new File(getOutputDirectory()),
new HTMLFileContentFilter(helper.getJavascriptTargetPath()),
TrueFileFilter.INSTANCE);
}
}