All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fcrepo.utilities.XmlTransformUtility Maven / Gradle / Ivy

There is a newer version: 6.5.0
Show newest version
/* The contents of this file are subject to the license and copyright terms
 * detailed in the license directory at the root of the source tree (also
 * available online at http://fedora-commons.org/license/).
 */
package org.fcrepo.utilities;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.SAXParser;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.pool.impl.SoftReferenceObjectPool;
import org.fcrepo.utilities.xml.PoolableDocumentBuilderFactory;
import org.fcrepo.utilities.xml.PoolableSAXParserFactory;
import org.fcrepo.utilities.xml.PoolableTransformerFactoryFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;


/**
 *
 * @author Edwin Shin
 * @version $Id$
 */
public class XmlTransformUtility {

    private static final Map> TEMPLATES_CACHE =
            new HashMap>();
    
    // A pool of namespace-aware DocumentBuilders
    // Using a Stack pool means that objectsare created on demand after the
    // pool is exhausted
    //TODO how should the default values be configured?
    private static final SoftReferenceObjectPool DOCUMENT_BUILDERS =
        new SoftReferenceObjectPool(
            new PoolableDocumentBuilderFactory(true, false));
    
    private static final SoftReferenceObjectPool TRANSFORM_FACTORIES =
        new SoftReferenceObjectPool(
            new PoolableTransformerFactoryFactory());
    
    private static final SoftReferenceObjectPool SAX_PARSERS =
        new SoftReferenceObjectPool(
            new PoolableSAXParserFactory(true, false));
        
    /**
     * Convenience method to get a new instance of a TransformerFactory.
     * If the {@link #TransformerFactory} is an instance of
     * net.sf.saxon.TransformerFactoryImpl, the attribute
     * {@link #FeatureKeys.VERSION_WARNING} will be set to false in order to
     * suppress the warning about using an XSLT1 stylesheet with an XSLT2
     * processor.
     *
     * @return a new instance of TransformerFactory
     * @throws Exception 
     */
    public static TransformerFactory borrowTransformerFactory() throws Exception {
        return (TransformerFactory) TRANSFORM_FACTORIES.borrowObject();
    }
    
    public static void returnTransformerFactory(TransformerFactory factory) {
        try {
            TRANSFORM_FACTORIES.returnObject(factory);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static Transformer getTransformer() throws Exception {
        return getTransformer(null);
    }
    public static Transformer getTransformer(Source src) throws Exception {
        TransformerFactory factory = null;
        Transformer result = null;
        try {
            factory = TRANSFORM_FACTORIES.borrowObject();
            result = (src == null) ? factory.newTransformer()
                    : factory.newTransformer(src);
            
        } finally {
            if (factory != null) {
                try {
                    TRANSFORM_FACTORIES.returnObject(factory);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
    
    /**
     * Try to cache parsed Templates, but check for changes on disk
     * @param src
     * @return
     */
    public static Templates getTemplates(File src) throws TransformerException {
        String key = src.getAbsolutePath();
        TimestampedCacheEntry entry = TEMPLATES_CACHE.get(key);
        // check to see if it is null or has changed
        if (entry == null || entry.timestamp() < src.lastModified()) {
            TransformerFactory factory = null;
            try {
                factory = borrowTransformerFactory();
                Templates template = factory.newTemplates(new StreamSource(src));
                entry = new TimestampedCacheEntry(src.lastModified(), template);
            } catch (Exception e) {
                throw new TransformerException(e.getMessage(), e);
            } finally {
                if (factory != null) returnTransformerFactory(factory);
            }
            TEMPLATES_CACHE.put(key, entry);
        }
        return entry.value();
    }
    
    public static Templates getTemplates(StreamSource source)
        throws TransformerException {
        TransformerFactory tf = null;
        Templates result = null;
        try {
            tf = borrowTransformerFactory();
            result = tf.newTemplates(source);
        } catch (Exception e) {
            throw new TransformerException(e.getMessage(), e);
        } finally {
            if (tf != null) returnTransformerFactory(tf);
        }
        return result;
    }
    
    public static DocumentBuilder borrowDocumentBuilder() throws Exception {
        return (DocumentBuilder) DOCUMENT_BUILDERS.borrowObject();
    }
    
    public static void returnDocumentBuilder(DocumentBuilder object) {
        try {
            DOCUMENT_BUILDERS.returnObject(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static Document parseNamespaceAware(File src)
            throws Exception {
        return parseNamespaceAware(new FileInputStream(src));
    }
    
    public static Document parseNamespaceAware(InputStream src)
        throws Exception {
        Document result = null;
        DocumentBuilder builder =
            (DocumentBuilder) DOCUMENT_BUILDERS.borrowObject();
        try {
            result = builder.parse(src);
        } finally {
            DOCUMENT_BUILDERS.returnObject(builder);
        }
        return result;
    }
    
    public static void parseWithoutValidating(InputStream in, DefaultHandler handler)
        throws SAXException, IOException {
        parseWithoutValidating(new InputSource(in), handler);
    }

    public static void parseWithoutValidating(InputSource in, DefaultHandler handler)
            throws SAXException, IOException {
        SAXParser parser = null;
        try {
            parser = (SAXParser) SAX_PARSERS.borrowObject();
        } catch (Exception e) {
            throw new RuntimeException("Error initializing SAX parser", e);
        }

        try {
            parser.parse(in, handler);
        } finally {
            if (parser != null) {
                try {
                    SAX_PARSERS.returnObject(parser);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy