com.wooki.services.parsers.XHTMLToFormattingObjects.java Source code

Java tutorial

Introduction

Here is the source code for com.wooki.services.parsers.XHTMLToFormattingObjects.java

Source

//
// Copyright 2009 Robin Komiwes, Bruno Verachten, Christophe Cordenier
//
// Licensed 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 com.wooki.services.parsers;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.log4j.Logger;
import org.springframework.core.io.Resource;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

public class XHTMLToFormattingObjects implements Convertor, URIResolver, EntityResolver {
    private TransformerFactory tFactory = TransformerFactory.newInstance();

    private Transformer transformer;

    private Resource xslStylesheet;

    private Map stylesheetParameters;

    private HttpClient httpClient;

    // Cache management
    private CacheManager cacheManager;

    private String cacheName;

    Cache cache;

    private Logger logger = Logger.getLogger(XHTMLToFormattingObjects.class);

    /**
     * This method is used to init the cache
     */
    @PostConstruct
    public void initCache() {
        logger.debug("Start to init " + cacheName + " cache");
        cache = cacheManager.getCache(cacheName);
        if (cache == null) {
            throw new IllegalArgumentException("Cache " + cacheName + " does not exist");
        }

        // HTML DTDs
        putInCache("xhtml1-strict.dtd", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
        putInCache("xhtml1-frameset.dtd", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd");
        putInCache("xhtml1-transitional.dtd", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd");

        // Entities
        putInCache("xhtml-lat1.ent", "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent");
        putInCache("xhtml-symbol.ent", "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent");
        putInCache("xhtml-special.ent", "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent");

        tFactory.setURIResolver(this);
        logger.debug("Init of " + cacheName + " is finished for xslt "/*
                                                                       * + xslStylesheet .
                                                                       * getDescription ()
                                                                       */);
    }

    private void putInCache(String fileLocation, String systemId) {
        try {
            InputStream in = this.getClass().getResourceAsStream(fileLocation);
            ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
            byte[] input = null;
            int available = 0;
            while ((available = in.available()) > 0) {
                int result;
                input = new byte[available];
                result = in.read(input);
                baos.write(input);
                if (result == -1)
                    break;
            }
            byte[] dtd = baos.toByteArray();
            Element element = new Element(systemId, dtd);
            cache.put(element);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("Didn't manage to put " + fileLocation + " in the \"" + cacheName
                    + "\" cache for systemId " + systemId);
            logger.error(e.getLocalizedMessage());
        }
    }

    public String getCacheName() {
        return cacheName;
    }

    public void setCacheName(String cacheName) {
        this.cacheName = cacheName;
    }

    public CacheManager getCacheManager() {
        return cacheManager;
    }

    public void setCacheManager(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    public HttpClient getHttpClient() {
        return httpClient;
    }

    public void setHttpClient(HttpClient httpClient) {
        this.httpClient = httpClient;
        HttpClientParams params = httpClient.getParams();
        // params.
        httpClient.setHttpConnectionManager(new MultiThreadedHttpConnectionManager());
    }

    public Resource getXslStylesheet() {
        return xslStylesheet;
    }

    public void setXslStylesheet(Resource xslStylesheet) {
        this.xslStylesheet = xslStylesheet;
    }

    public Map getStylesheetParameters() {
        return stylesheetParameters;
    }

    public void setStylesheetParameters(Map stylesheetParameters) {
        this.stylesheetParameters = stylesheetParameters;
    }

    public InputStream performTransformation(Resource xmlDocument) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        StreamResult toReturn = new StreamResult(baos);

        // Use the TransformerFactory to instantiate a Transformer that will
        // work with the stylesheet you specify. This method call also processes
        // the stylesheet into
        // a compiled Templates object.

        try {
            URL url = this.xslStylesheet.getURL();
            Element processedStylesheet = cache.get(url);
            if (processedStylesheet == null) {

                if (url.getProtocol().equals("http")) {
                    GetMethod method = new GetMethod(url.toString());
                    this.httpClient.executeMethod(method);
                    byte[] body = method.getResponseBody();
                    StreamSource input = new StreamSource(new ByteArrayInputStream(body));
                    input.setSystemId(url.toString());
                    tFactory.setURIResolver(this);
                    transformer = tFactory.newTransformer(input);
                    transformer.setURIResolver(this);
                    processedStylesheet = new Element(this.xslStylesheet.getURL(), transformer);
                } else {
                    StreamSource input = new StreamSource(this.xslStylesheet.getInputStream());
                    input.setSystemId(this.xslStylesheet.getFile());
                    transformer = tFactory.newTransformer(input);
                    transformer.setURIResolver(this);
                    processedStylesheet = new Element(this.xslStylesheet.getURL(), transformer);
                }
                cache.put(processedStylesheet);
            } else {
                transformer = (Transformer) processedStylesheet.getObjectValue();
            }
            XMLReader reader = XMLReaderFactory.createXMLReader();
            reader.setEntityResolver(this);

            // transformer.
            // Use the Transformer to apply the associated Templates object to
            // an
            // XML document (foo.xml) and write the output to a file.
            transformer.transform(new SAXSource(reader, new InputSource(xmlDocument.getInputStream())), toReturn);
            String result = new String(baos.toByteArray());
            return new ByteArrayInputStream(baos.toByteArray());
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
            logger.error(e.getLocalizedMessage());
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getLocalizedMessage());
            return null;
        } catch (TransformerException e) {
            e.printStackTrace();
            logger.error(e.getLocalizedMessage());
            return null;
        } catch (SAXException e) {
            e.printStackTrace();
            logger.error(e.getLocalizedMessage());
            return null;
        } catch (Error e) {
            e.printStackTrace();
            logger.error(e.getLocalizedMessage());
        }
        return new ByteArrayInputStream(baos.toByteArray());
    }

    public Source resolve(String href, String base) throws TransformerException {
        Source toReturn = null;
        if (base != null && base.contains("file://")) {
            String newPath = base.substring("file:///".length()).replace('/', File.separatorChar);
            newPath = newPath.substring(0, newPath.lastIndexOf(File.separatorChar));
            File baseFile = new File(newPath);
            baseFile = new File(
                    baseFile.getAbsolutePath() + File.separatorChar + href.replace('/', File.separatorChar));
            try {
                toReturn = new StreamSource(new FileInputStream(baseFile));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                logger.error(e.getLocalizedMessage());
                return null;
            }
        } else {
            if (base.contains("http://")) {
                String newUrl = base.substring(0, base.lastIndexOf('/') + 1);
                newUrl += href;
                HttpMethod get = new GetMethod(newUrl);
                try {
                    httpClient.executeMethod(get);
                    byte[] body = get.getResponseBody();
                    Element element = new Element(newUrl, body);
                    cache.put(element);
                    toReturn = new StreamSource(new BufferedInputStream(new ByteArrayInputStream(body)));
                } catch (HttpException e) {
                    e.printStackTrace();
                    logger.error(e.getLocalizedMessage());
                    return null;
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error(e.getLocalizedMessage());
                    return null;
                }
                toReturn.setSystemId(newUrl);
            } else {
                toReturn = new StreamSource(XHTMLToFormattingObjects.class.getResourceAsStream(href));
            }
        }
        return toReturn;
    }

    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
        InputSource toReturn = null;
        Element cachedValue = cache.get(systemId);
        if (cachedValue == null) {
            if (systemId.contains("http://")) {
                HttpMethod get = new GetMethod(systemId);
                httpClient.executeMethod(get);
                byte[] body = get.getResponseBody();
                Element element = new Element(systemId, body);
                cache.put(element);
                toReturn = new InputSource(new BufferedInputStream(new ByteArrayInputStream(body)));
                toReturn.setSystemId(systemId);
            } else if (systemId.contains("file://")) {
                String newPath = systemId.substring("file:///".length()).replace('/', File.separatorChar);
                File baseFile = new File(newPath);
                try {
                    toReturn = new InputSource(new FileInputStream(baseFile));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    logger.error(e.getLocalizedMessage());
                    return null;
                }
            }
        } else {
            toReturn = new InputSource(
                    new BufferedInputStream(new ByteArrayInputStream((byte[]) cachedValue.getObjectValue())));
            toReturn.setSystemId(systemId);
        }
        return toReturn;
    }

}