Package net.sourceforge.yagsbook.pagexml

Source Code of net.sourceforge.yagsbook.pagexml.Yagsbook$LocalResolver

/*
* Copyright (C) 2009 Samuel Penn, sam@glendale.org.uk
*
* This program 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 version 2.
* See the file COPYING.
*
* $Revision: 1.13 $
* $Date: 2009/06/28 09:43:08 $
*/
package net.sourceforge.yagsbook.pagexml;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;

import org.apache.tools.ant.taskdefs.Cvs;

import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.zip.*;

import org.apache.xpath.XPathAPI;

import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

import org.apache.fop.apps.*;


/**
* XSLT plugin for handling PageXML files. Supports generation of rule
* sets and encyclopedias as referenced by the source XML.
*
* Updated 2009/05/10 for Fop 0.9X
*
* @author Samuel Penn.
*/
public class Yagsbook extends Cvs {
    private String      localRepository;
    private String      destination;
    private String      relativePath;

    private String      targetDir = "html";
    private String      tmpDir = "tmp";

    // Location of XSLT files.
    private static final String XSLT_BASE =
                                    "/usr/share/xml/yagsbook/article/xslt";
    private static final String XSLT_HTML = XSLT_BASE+"/html/yagsbook.xsl";
    private static final String XSLT_PDF = XSLT_BASE+"/pdf/yagsbook.xsl";
    //private static final String XSLT_PDF="/home/sam/src/forge/yagsbook/xml/xslt/pdf/yagsbook.xsl";

    class XMLException extends Exception {
        XMLException(String msg) {
            super(msg);
        }
    }

    /**
     * Resolve links to external documents so that relative files are found.
     */
    public class LocalResolver implements URIResolver {
        private String  baseDir;

        LocalResolver(String baseDir) {
            this.baseDir = baseDir;
        }

        public Source
        resolve(String href, String base) {
            File    file = new File(href);
            URL     url = null;
            String  fullPath = null;
            Source  src = null;

            try {
                if (href.startsWith("http:")) {
                    url = new URL(href);
                    src = new StreamSource(url.openStream());
                } else if (file.isAbsolute()) {
                    src = new StreamSource(new File(href));
                } else {
                    src = new StreamSource(new File(baseDir+"/"+href));
                }
            } catch (Exception e) {
                System.out.println("resolve: "+e.getMessage());
            }

            return src;
        }
    }

    public Yagsbook() {
        setProject(new Project());
        getProject().init();
        setTaskType("cvs");
        setTaskName("cvs");
        target = new Target();
    }

    public void
    setTargetDir(String targetDir) {
        this.targetDir = targetDir;
    }

    public void
    setTmpDir(String tmpDir) {
        this.tmpDir = tmpDir;
    }

    /**
     * Import all available Yagsbook documents into the website.
     * The specified CVS repository is exported, and all the '.yags' files
     * in the top level directory are converted to HTML and PDF format.
     *
     * @param module    Name of the CVS module to process.
     * @param subdir    Sub directory beneath the CVS module to process.
     * @param cvsroot   Path to the CVS repository. This can be a pserver URL.
     * @param basedir   Base directory.
     */
    public String
    importBooks(String module, String subdir, String cvsroot, String basedir) {
        export(module, tmpDir+"/", cvsroot);
        localRepository = tmpDir+"/"+module+"/"+subdir;
        destination = targetDir+"/"+basedir+"/"+subdir;
        relativePath = subdir;

        try {
            new File(destination).mkdirs();
            new File(tmpDir).mkdirs();
        } catch (Exception e) {
        }

        String  output = null;
        try {
            File        directory = new File(localRepository);
            if (directory.isDirectory()) {
                output = processFiles(directory.list());
            } else {
                System.out.println("Not a directory");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        deleteDir(new File(tmpDir));

        return output;
    }


    public String
    importEncyclopedia(String module, String destdir, String cvsroot, String basedir) {
        export(module, tmpDir+"/", cvsroot);
        localRepository = tmpDir+"/"+module;
        destination = targetDir+"/"+basedir+"/"+destdir;
        relativePath = destdir;

        try {
            new File(destination).mkdirs();
            new File(tmpDir).mkdirs();
        } catch (Exception e) {
        }

        String      output = null;
        try {
        } catch (Exception e) {
            e.printStackTrace();
        }

        return output;
    }

    private void
    deleteDir(File dir) {
        try {
            File[]    list = dir.listFiles();
            for (int i=0; i < list.length; i++) {
                if (list[i].isDirectory()) {
                    deleteDir(list[i]);
                } else {
                    list[i].delete();
                }
            }
            dir.delete();
        } catch (Exception e) {
        }
    }

    /**
     * Process the list of files, in alphabetical order. Each file (if it
     * ends with a '.yags' suffix) is transformed via XSL, and an entry
     * added for it into the HTML string which is returned. This string
     * consists of links to each HTML document, plus a summary paragraph
     * describing the document (taken from the header/summary element of
     * the yagsbook document.
     *
     * @param files     Array of filenames to be processed.
     * @return          HTML string describing all the files processed.
     */
    String
    processFiles(String[] files) {
        StringBuffer    buffer = new StringBuffer();

        Arrays.sort(files);
        for (int i=0; i < files.length; i++) {
            String  name = files[i];
            if (name.endsWith(".yags")) {
                System.out.println("Transforming "+name);
                buffer.append(transform(name));
            }
        }

        return buffer.toString();
    }

    private Document
    load(String filename) throws XMLException {
        return load(filename, false);
    }

    private Document
    load(String filename, boolean useNameSpace) throws XMLException {
        try {
            InputSource                 in;
            DocumentBuilderFactory      dbf;

            in = new InputSource(new FileInputStream(new File(filename)));
            dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(useNameSpace);

            return dbf.newDocumentBuilder().parse(in);
        } catch (ParserConfigurationException pce) {
            throw new XMLException("Cannot configure parser for ["+filename+"]: "+
                                    pce.getMessage());
        } catch (SAXException se) {
            throw new XMLException("Cannot parse document ["+filename+"]: "+
                                    se.getMessage());
        } catch (IOException ioe) {
            throw new XMLException("Cannot find file ["+filename+"]: "+
                                    ioe.getMessage());
        }
    }

    private String
    getSummary(Document doc) {
        String      summary = "";
        String      xpath = "/article/header/summary";

        try {
            Node        node = XPathAPI.selectSingleNode(doc, xpath);
            if (node != null) {
                if (node.hasChildNodes()) {
                    node = node.getFirstChild();
                    summary = node.getNodeValue();
                }
            }
        } catch (TransformerException te) {
            System.out.println(te.getMessage());
        }

        return summary;
    }

    private String
    getTitle(Document doc) {
        String      summary = "";
        String      xpath = "/article/header/title";

        try {
            Node        node = XPathAPI.selectSingleNode(doc, xpath);
            if (node != null) {
                if (node.hasChildNodes()) {
                    node = node.getFirstChild();
                    summary = node.getNodeValue();
                }
            }
        } catch (TransformerException te) {
            System.out.println(te.getMessage());
        }

        return summary;
    }

    public String
    applyStylesheet(String stylesheet, Document doc) throws XMLException {
        StringWriter    writer = new StringWriter();

        try {
            File        xsltFile = new File(stylesheet);
            Source      xslt = new StreamSource(xsltFile);
            Source      xml = new DOMSource(doc);
            Result      html = new StreamResult(writer);

            TransformerFactory  fact = TransformerFactory.newInstance();
            Transformer         trans = fact.newTransformer(xslt);

            LocalResolver       local = new LocalResolver(localRepository);
            trans.setURIResolver(local);
            trans.transform(xml, html);
        } catch (TransformerConfigurationException tce) {
            tce.printStackTrace();
            throw new XMLException("Cannot configure transform: "+
                                    tce.getMessage());
        } catch (TransformerException te) {
            te.printStackTrace();
            throw new XMLException("Cannot apply stylesheet: "+
                                    te.getMessage());
        }

        return writer.toString();
    }

    /**
     * Given an XSL-FO file, convert it to PDF and write out to the
     * provided destination file. Uses Apache FOP to do all the hard
     * work of generating the PDF.
     *
     * @param fo        Input file containing XSL-FO.
     * @param pdf       Output file to write PDF to.
     *
     * @return          True if a PDF could be generated.
     */
    private boolean
    writePdf(File fo, File pdf) {
        boolean     success = false;
        FopFactory  factory = FopFactory.newInstance();
        FOUserAgent userAgent = factory.newFOUserAgent();
        Fop         fop = null;

        //Configuration.put("baseDir", localRepository);
        userAgent.setBaseURL(localRepository);

        // Create output stream for writing PDF to.
        OutputStream    stream = null;
        try {
            stream = new BufferedOutputStream(new FileOutputStream(pdf));
            fop = factory.newFop(MimeConstants.MIME_PDF, userAgent, stream);
            //driver.setOutputStream(stream);
        } catch (FileNotFoundException e) {
            System.out.println("Failed to find file ["+
                               pdf.getAbsolutePath()+"]");
            return success;
        } catch (FOPException e) {
            e.printStackTrace();
            return success;
        }

        try {
            TransformerFactory tfactory = TransformerFactory.newInstance();
            Transformer transformer = tfactory.newTransformer();

            // Setup input stream and parse results.
            Source src = new StreamSource(fo);
            Result result = new SAXResult(fop.getDefaultHandler());
            transformer.transform(src, result);

            stream.close();
            success = true;
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (FOPException e) {
            e.printStackTrace();
        }

        return success;
    }

    /**
     * Transform the given Yagsbook XML file into both HTML and PDF
     * renditions. The resulting files will have the same base name,
     * with either a '.html' or '.pdf' suffix. Any external images
     * referenced by the document are copied to the destination
     * location. They are currently assumed to be in the directory
     * local to the document.
     */
    String transform(String name) {
        StringBuffer    output = new StringBuffer();
        String          baseName = name.replaceAll("\\.yags", "");
        FileWriter      writer = null;

        try {
            Document    doc = load(localRepository+"/"+name, true);
            String      html = applyStylesheet(XSLT_HTML, doc);
            String      htmlName = destination+"/"+baseName+".html";
            String      pdfName = destination+"/"+baseName+".pdf";

            // Write out the HTML file.
            writer = new FileWriter(htmlName);
            writer.write(html);
            writer.close();

            // Write out the Formatting Objects file.
            boolean     havePdf = false;

            try {
                String      fo = applyStylesheet(XSLT_PDF, doc);
                File        tmpFo = File.createTempFile(baseName, ".fo");
                writer = new FileWriter(tmpFo);
                writer.write(fo);
                writer.close();

                // Now convert the formatting objects to PDF.
                havePdf = writePdf(tmpFo, new File(pdfName));
            } catch (Exception e) {
                e.printStackTrace();
            }
            // Can't use XPath if using a namespace.
            doc = load(localRepository+"/"+name, false);
            copyImages(doc);

            String  htmlHref = relativePath + "/" + baseName+".html";
            String  pdfHref = relativePath+"/"+baseName+".pdf";

            output.append("<p><a href=\""+htmlHref+"\">");
            output.append(getTitle(doc)+"</a>");
            if (havePdf) {
                output.append(" (<a href=\""+pdfHref+"\">PDF</a>)");
            }
            output.append(": ");
            output.append(getSummary(doc));
            output.append("</p>\n");
        } catch (XMLException xmle) {
            xmle.printStackTrace();
            System.out.println(xmle.getMessage());
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        }

        return output.toString();
    }

    /**
     * Copy the given file into the specified directory. The name of
     * the file is always preserved.
     *
     * @param file      The file to be copied.
     * @param path      The path to the destination directory.
     */
    private void
    copyFile(File file, File destination) throws IOException {
        String  outpath  =  destination.getPath()+"/"+file.getName();
        byte[]  data  = new byte[65536];
        int     len = 0;

        File    dest = new File(outpath);
        if (dest.exists()) {
            // If the file already exists at the destination, then
            // don't bother copying.
            return;
        }

        FileInputStream  fis = new FileInputStream(file);
        FileOutputStream fos = new FileOutputStream(outpath);

        while ((len = fis.read(data)) >= 0) {
            fos.write(data, 0, len);
        }

        fis.close();
        fos.close();
    }

    /**
     * Finds all the external images referenced in the document and copies
     * them into the destination directory.
     */
    void copyImages(Document doc) {
        NodeList    list = null;
        Node        node = null;
        String      xpath = "//svg/@src";


        try {
            list = XPathAPI.selectNodeList(doc, xpath);

            for (int i=0; i < list.getLength(); i++) {
                node = list.item(i);
                String  path = node.getNodeValue();
                System.out.println(i+": SVG ["+path+"]");
                copyFile(new File(localRepository+"/"+path), new File(destination));
            }
        } catch (TransformerException e) {
            System.out.println("copyImages: XML Exception ("+e.getMessage()+")");
        } catch (IOException e) {
            System.out.println("copyImages: IO Exception ("+e.getMessage()+")");
        }
    }

    void
    export(String srcdir, String destdir, String cvsroot) {
        try {
            setCvsRoot(cvsroot);
            setCommand("export");
            setDest(new File(destdir));
            setDate("TODAY");
            setPackage(srcdir);
            //setPassfile(new File("~/.cvspass"));
            execute();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return;
    }

    public void
    test() {
        StringBuffer    output = new StringBuffer();
        StringWriter      writer = new StringWriter();

        try {
            InputSource                 in;
            DocumentBuilderFactory      dbf;

            in = new InputSource(new FileInputStream(new File("/home/sam/foo.xml")));
            dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);

            Document    doc = dbf.newDocumentBuilder().parse(in);

            File        xsltFile = new File("/home/sam/foo.xslt");
            Source      xslt = new StreamSource(xsltFile);
            Source      xml = new DOMSource(doc);
            Result      html = new StreamResult(writer);

            TransformerFactory  fact = TransformerFactory.newInstance();
            Transformer         trans = fact.newTransformer(xslt);

            LocalResolver       local = new LocalResolver("/tmp");
            trans.setURIResolver(local);
            trans.transform(xml, html);

            System.out.println(writer.toString());
        } catch (Exception xmle) {
            xmle.printStackTrace();
            System.out.println(xmle.getMessage());
        }


    }

    private String archiveDirectory(ZipOutputStream stream, File directory) {
        StringBuffer    buffer = new StringBuffer();
        String[]        list = directory.list();

        for (int i=0; i < list.length; i++) {
            File    file = new File(directory.getAbsolutePath()+"/"+list[i]);
            if (file.isDirectory()) {
                buffer.append(archiveDirectory(stream, file));
            } else {
                ZipEntry    zip = new ZipEntry(list[i]);
            }
        }

        return buffer.toString();
    }

    /**
     * Create a ZIP archive of all the source files.
     */
    private String archiveSource(File rootDir) throws FileNotFoundException {
        String  output = null;

        if (!rootDir.isDirectory()) {
            System.out.println("Can only archive files in a directory");
            return "";
        }

        File            zip = new File("/tmp/test.zip");
        ZipOutputStream stream = new ZipOutputStream(new FileOutputStream(zip));

        archiveDirectory(stream, rootDir);
        try {
            File        directory = new File(localRepository);
            if (directory.isDirectory()) {
                output = processFiles(directory.list());
            } else {
                System.out.println("Not a directory");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        deleteDir(new File(tmpDir));

        return output;
    }

    public static void
    main(String[] args) {
        Yagsbook    yb = new Yagsbook();
        String      result = null;
        result = yb.importBooks("yags", "habisfern",
                                ":pserver:sam@cvshost:2401/var/cvs/rpg",
                                "output");
        //yb.importEncyclopedia("habisfern/encyclopedia", "html",
        //                     ":pserver:sam@cvshost:2401/var/cvs/rpg", "html");

        //yb.destination = "/tmp";
        //yb.localRepository = "/home/sam/rpg/yags/habisfern/";
        //yb.relativePath = ".";
        //result = yb.transform("magic.yags");
        //yb.writePdf(new File("/tmp/foo.fo"), new File("/tmp/foo.pdf"));
        System.out.println(result);
    }

}
TOP

Related Classes of net.sourceforge.yagsbook.pagexml.Yagsbook$LocalResolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.