blob: 573ca368c6afb7402c0885512d4300d17e279039 [file] [log] [blame]
/* gnu.classpath.tools.doclets.xmldoclet.doctranslet.DocTranslet
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
package gnu.classpath.tools.doclets.xmldoclet.doctranslet;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.jar.Attributes;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import gnu.classpath.tools.IOToolkit;
import gnu.classpath.tools.doclets.xmldoclet.Driver;
import com.sun.javadoc.DocErrorReporter;
public class DocTranslet implements ErrorListener {
private static class DocErrorReporterOutputStream
extends OutputStream
{
private ByteArrayOutputStream out = new ByteArrayOutputStream();
private DocErrorReporter reporter;
public DocErrorReporterOutputStream(DocErrorReporter reporter) {
this.reporter = reporter;
}
public void write(int ch) {
out.write(ch);
if (ch == 10) {
reporter.printNotice(out.toString());
out.reset();
}
}
}
private String mainResourceFilename;
private ClassLoader classLoader;
private Map transformerMap = new java.util.HashMap(); //WeakHashMap();
private DocTransletOptions options;
protected DocTranslet(String mainResourceFilename,
ClassLoader classLoader)
throws DocTransletConfigurationException {
if (mainResourceFilename.length() > 0 && mainResourceFilename.charAt(0) == '/') {
mainResourceFilename = mainResourceFilename.substring(1);
}
this.mainResourceFilename = mainResourceFilename;
this.classLoader = classLoader;
}
private static boolean equalsFile(File file1, File file2) {
return file1.getAbsolutePath().equals(file2.getAbsolutePath());
}
private static File getParentFile(File file) {
String filename = file.getAbsolutePath();
if (filename.endsWith(File.separator)) {
filename = filename.substring(0, filename.length() - 1);
}
int lastSlash = filename.lastIndexOf(File.separatorChar);
if (lastSlash > 0) {
filename = filename.substring(0, lastSlash);
}
else {
filename = File.separator;
}
return new File(filename);
}
private static boolean cacheXSLTSheets = true;
public void apply(File xmlSourceDirectory, File targetDirectory,
DocErrorReporter reporter)
throws DocTransletException {
PrintStream err = System.err;
try{
URL mainResourceURL = classLoader == null ?
ClassLoader.getSystemResource(mainResourceFilename):
classLoader.getResource(mainResourceFilename);
if (null == mainResourceURL) {
throw new DocTransletException("Cannot find resource '" + mainResourceFilename + "'");
}
Map parameters = new HashMap();
parameters.put("gjdoc.xmldoclet.version", Driver.XMLDOCLET_VERSION);
parameters.put("gjdoc.option.nonavbar", xsltBoolean(options.nonavbar));
parameters.put("gjdoc.option.noindex", xsltBoolean(options.noindex));
parameters.put("gjdoc.option.notree", xsltBoolean(options.notree));
parameters.put("gjdoc.option.nocomment", xsltBoolean(options.nocomment));
parameters.put("gjdoc.option.nohelp", xsltBoolean(options.nohelp));
parameters.put("gjdoc.option.splitindex", xsltBoolean(options.splitindex));
parameters.put("gjdoc.option.linksource", xsltBoolean(options.linksource));
parameters.put("gjdoc.option.nodeprecatedlist", xsltBoolean(options.nodeprecatedlist));
parameters.put("gjdoc.option.uses", xsltBoolean(options.uses));
parameters.put("gjdoc.option.windowtitle", options.windowtitle);
parameters.put("gjdoc.option.helpfile", options.helpfile);
parameters.put("gjdoc.option.stylesheetfile", options.stylesheetfile);
parameters.put("gjdoc.option.header", options.header);
parameters.put("gjdoc.option.footer", options.footer);
parameters.put("gjdoc.option.bottom", options.bottom);
parameters.put("gjdoc.option.doctitle", options.doctitle);
List outputFileList = getOutputFileList(mainResourceURL,
xmlSourceDirectory,
parameters);
reporter.printNotice("Running DocTranslet...");
TransformerFactory transformerFactory
= TransformerFactory.newInstance();
transformerFactory.setErrorListener(this);
boolean isLibxmlJ
= transformerFactory.getClass().getName().equals("gnu.xml.libxmlj.transform.TransformerFactoryImpl");
for (Iterator it = outputFileList.iterator(); it.hasNext(); ) {
if (isLibxmlJ) {
System.gc();
Runtime.getRuntime().runFinalization();
}
OutputFileInfo fileInfo = (OutputFileInfo)it.next();
File targetFile = new File(targetDirectory, fileInfo.getName());
File packageTargetDir = getParentFile(targetFile);
if (!packageTargetDir.exists() && !packageTargetDir.mkdirs()) {
throw new DocTransletException("Target directory " + packageTargetDir + " does not exist and cannot be created.");
}
if (options.linksource) {
File sourceTargetDirectory = new File(targetDirectory, "src-html");
File sourceTargetFile = new File(sourceTargetDirectory, fileInfo.getName());
File sourcePackageTargetDir = getParentFile(sourceTargetFile);
if (!sourcePackageTargetDir.exists() && !sourcePackageTargetDir.mkdirs()) {
throw new DocTransletException("Target directory " + packageTargetDir + " does not exist and cannot be created.");
}
}
if (options.uses) {
File usesTargetDirectory = new File(targetDirectory, "class-use");
File usesTargetFile = new File(usesTargetDirectory, fileInfo.getName());
File usesPackageTargetDir = getParentFile(usesTargetFile);
if (!usesPackageTargetDir.exists() && !usesPackageTargetDir.mkdirs()) {
throw new DocTransletException("Target directory " + packageTargetDir + " does not exist and cannot be created.");
}
}
if (null != fileInfo.getSource()) {
reporter.printNotice("Copying " + fileInfo.getComment() + "...");
InputStream in = new URL(mainResourceURL, fileInfo.getSource()).openStream();
FileOutputStream out = new FileOutputStream(targetFile.getAbsolutePath());
IOToolkit.copyStream(in, out);
in.close();
out.close();
}
else {
reporter.printNotice("Generating " + fileInfo.getComment() + "...");
String pathToRoot = "";
for (File file = getParentFile(targetFile); !equalsFile(file, targetDirectory); file = getParentFile(file)) {
pathToRoot += "../";
}
StreamResult out = new StreamResult(targetFile.getAbsolutePath());
StreamSource in = new StreamSource(new File(xmlSourceDirectory, "index.xml").getAbsolutePath());
URL resource = new URL(mainResourceURL, fileInfo.getSheet());
StreamSource xsltSource = new StreamSource(resource.toExternalForm());
if (null != fileInfo.getInfo()) {
parameters.put("gjdoc.outputfile.info", fileInfo.getInfo());
}
parameters.put("gjdoc.pathtoroot", pathToRoot);
Transformer transformer;
transformer = (Transformer)transformerMap.get(xsltSource.getSystemId());
if (null == transformer) {
transformer = transformerFactory.newTransformer(xsltSource);
if (cacheXSLTSheets) {
transformerMap.put(xsltSource.getSystemId(), transformer);
}
}
transformer.clearParameters();
for (Iterator pit = parameters.keySet().iterator(); pit.hasNext(); ) {
String key = (String)pit.next();
String value = (String)parameters.get(key);
transformer.setParameter(key, value);
}
transformer.setErrorListener(this);
DocErrorReporterOutputStream errorReporterOut
= new DocErrorReporterOutputStream(reporter);
System.setErr(new PrintStream(errorReporterOut));
transformer.transform(in, out);
errorReporterOut.flush();
}
}
}
catch (MalformedURLException e) {
throw new DocTransletException(e);
}
catch (TransformerFactoryConfigurationError e) {
throw new DocTransletException(e);
}
catch (TransformerException e) {
throw new DocTransletException(e.getMessageAndLocation(), e);
}
catch (IOException e) {
throw new DocTransletException(e);
}
finally {
System.setErr(err);
}
}
private List getOutputFileList(URL resource, File xmlSourceDirectory, Map parameters)
throws DocTransletException {
try {
List result;
OutputStream out = new ByteArrayOutputStream();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
DOMResult domResult = new DOMResult(document);
{
StreamSource source = new StreamSource(resource.toExternalForm());
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = (Transformer)transformerFactory.newTransformer(source);
transformer.clearParameters();
for (Iterator pit = parameters.keySet().iterator(); pit.hasNext(); ) {
String key = (String)pit.next();
String value = (String)parameters.get(key);
transformer.setParameter(key, value);
}
transformer.transform(new StreamSource(new File(xmlSourceDirectory,
"index.xml").getAbsolutePath()),
domResult);
}
{
NodeList nodeList = document.getElementsByTagName("outputfile");
result = new ArrayList(nodeList.getLength());
for (int i=0; i<nodeList.getLength(); ++i) {
Element elem = (Element)nodeList.item(i);
String name = getTextContent(elem.getElementsByTagName("name").item(0));
String source
= (null != elem.getElementsByTagName("source").item(0))
? getTextContent(elem.getElementsByTagName("source").item(0))
: null;
String sheet
= (null != elem.getElementsByTagName("sheet").item(0))
? getTextContent(elem.getElementsByTagName("sheet").item(0))
: null;
String comment = getTextContent(elem.getElementsByTagName("comment").item(0));
String info = null;
if (elem.getElementsByTagName("info").getLength() > 0) {
if (null != elem.getElementsByTagName("info").item(0).getFirstChild()) {
info = getTextContent(elem.getElementsByTagName("info").item(0));
}
else {
info = "";
}
}
result.add(new OutputFileInfo(name, source, sheet, comment, info));
}
}
return result;
}
catch (TransformerFactoryConfigurationError e) {
throw new DocTransletException(e);
}
catch (TransformerException e) {
throw new DocTransletException(e.getMessageAndLocation(), e);
}
catch (ParserConfigurationException e) {
throw new DocTransletException(e);
}
}
private String getTextContent(Node elem)
{
StringBuffer result = new StringBuffer();
NodeList children = elem.getChildNodes();
for (int i=0; i<children.getLength(); ++i) {
Node item = children.item(i);
if (null != item) {
String value = item.getNodeValue();
if (null != value) {
result.append(value);
}
}
}
return result.toString();
}
public void setOptions(DocTransletOptions options) {
this.options = options;
}
public static DocTranslet fromClasspath(String resourceName)
throws DocTransletConfigurationException {
return new DocTranslet(resourceName,
DocTranslet.class.getClassLoader());
}
public static DocTranslet fromJarFile(File jarFile)
throws DocTransletConfigurationException {
try {
JarFile inputJarFile = new JarFile(jarFile, false, JarFile.OPEN_READ);
Manifest manifest = inputJarFile.getManifest();
if (null == manifest) {
throw new DocTransletConfigurationException("Jar file '" + jarFile + "' doesn't contain a manifest.");
}
Attributes mainAttributes = manifest.getMainAttributes();
String docTransletMainEntry = mainAttributes.getValue("doctranslet-main-entry");
if (null == docTransletMainEntry) {
throw new DocTransletConfigurationException("Manifest in Jar file '" + jarFile + "' doesn't contain a doctranslet-main-entry specification.");
}
return new DocTranslet(docTransletMainEntry,
new JarClassLoader(inputJarFile));
}
catch (IOException e) {
throw new DocTransletConfigurationException(e);
}
}
private static String xsltBoolean(boolean b) {
return b ? "1" : "";
}
public void error (TransformerException exception)
throws TransformerException {
throw exception;
}
public void fatalError (TransformerException exception)
throws TransformerException {
throw exception;
}
public void warning (TransformerException exception)
throws TransformerException {
System.err.println("WWW: " + exception.getMessage());
}
}