| /* 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()); |
| } |
| } |