    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/framework/xml/XSLTDocument.java $
    002    /*----------------------------------------------------------------------------
    003     This file is part of deegree, http://deegree.org/
    004     Copyright (C) 2001-2009 by:
    005       Department of Geography, University of Bonn
    006     and
    007       lat/lon GmbH
    008
    009     This library is free software; you can redistribute it and/or modify it under
    010     the terms of the GNU Lesser General Public License as published by the Free
    011     Software Foundation; either version 2.1 of the License, or (at your option)
    012     any later version.
    013     This library is distributed in the hope that it will be useful, but WITHOUT
    014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    016     details.
    017     You should have received a copy of the GNU Lesser General Public License
    018     along with this library; if not, write to the Free Software Foundation, Inc.,
    019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    020
    021     Contact information:
    022
    023     lat/lon GmbH
    024     Aennchenstr. 19, 53177 Bonn
    025     Germany
    026     http://lat-lon.de/
    027
    028     Department of Geography, University of Bonn
    029     Prof. Dr. Klaus Greve
    030     Postfach 1147, 53001 Bonn
    031     Germany
    032     http://www.geographie.uni-bonn.de/deegree/
    033
    034     e-mail: info@deegree.org
    035    ----------------------------------------------------------------------------*/
    036    package org.deegree.framework.xml;
    037
    038    import java.io.IOException;
    039    import java.io.InputStream;
    040    import java.io.OutputStream;
    041    import java.io.Reader;
    042    import java.net.MalformedURLException;
    043    import java.net.URL;
    044    import java.util.Iterator;
    045    import java.util.Map;
    046    import java.util.Properties;
    047
    048    import javax.xml.transform.Result;
    049    import javax.xml.transform.Source;
    050    import javax.xml.transform.Transformer;
    051    import javax.xml.transform.TransformerException;
    052    import javax.xml.transform.TransformerFactory;
    053    import javax.xml.transform.dom.DOMResult;
    054    import javax.xml.transform.dom.DOMSource;
    055    import javax.xml.transform.stream.StreamResult;
    056    import javax.xml.transform.stream.StreamSource;
    057
    058    import org.deegree.framework.log.ILogger;
    059    import org.deegree.framework.log.LoggerFactory;
    060    import org.deegree.framework.util.BootLogger;
    061    import org.w3c.dom.Document;
    062    import org.xml.sax.SAXException;
    063
    064    /**
    065     * Encapsulates the DOM representation of an XSLT stylesheet.
    066     *
    067     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a>
    068     *
    069     * @author last edited by: $Author: mschneider $
    070     *
    071     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    072     *
    073     */
    074    public class XSLTDocument extends XMLFragment {
    075
    076        private static final long serialVersionUID = -2079718341146916400L;
    077
    078        private static final ILogger LOG = LoggerFactory.getLogger( XSLTDocument.class );
    079
    080        private static final TransformerFactory factory = TransformerFactory.newInstance();
    081
    082        static {
    083            LOG.logDebug( "XSLT implementation in use (TransformerFactory): " + factory.getClass().getName() );
    084            try {
    085                LOG.logDebug( "XSLT implementation in use (Transformer): " + factory.newTransformer().getClass().getName() );
    086            } catch ( Exception e ) {
    087                BootLogger.logError( "Error creating test Transformer instance.", e );
    088            }
    089        }
    090
    091        /**
    092         * An empty xslt document.
    093         */
    094        public XSLTDocument() {
    095            super();
    096        }
    097
    098        /**
    099         *
    100         * @param url
    101         * @throws IOException
    102         * @throws SAXException
    103         */
    104        public XSLTDocument( URL url ) throws IOException, SAXException {
    105            super( url );
    106        }
    107
    108        /**
    109         * Transforms the given <code>XMLFragment</code> instance.
    110         *
    111         * @param xmlDocument
    112         *            can not be null
    113         * @param systemId
    114         *            SystemID for the resulting <code>XMLFragment</code>, may be null
    115         * @param outputProperties
    116         *            transformation properties, may be null
    117         * @param params
    118         *            transformation parameters, may be null
    119         * @return the transformed xml file.
    120         * @throws TransformerException
    121         * @throws MalformedURLException
    122         *             if systemId is no valid <code>URL</code>
    123         */
    124        public synchronized XMLFragment transform( XMLFragment xmlDocument, String systemId, Properties outputProperties,
    125                                                   Map<String, ?> params )
    126                                throws TransformerException, MalformedURLException {
    127
    128            XMLFragment resultFragment = null;
    129            DOMSource xmlSource = new DOMSource( xmlDocument.getRootElement() );
    130            DOMSource xslSource = new DOMSource( this.getRootElement().getOwnerDocument(),
    131                                                 this.getSystemId() == null ? null : this.getSystemId().toString() );
    132            Result result = transform( xmlSource, xslSource, new DOMResult(), outputProperties, params );
    133            Document resultDocument = (Document) ( (DOMResult) result ).getNode();
    134            resultFragment = new XMLFragment( resultDocument, systemId );
    135
    136            return resultFragment;
    137        }
    138
    139        /**
    140         * Transforms the given <code>XMLFragment</code> instance.
    141         *
    142         * @param xmlDocument
    143         *            can not be null
    144         * @return the transformed xml file.
    145         * @throws TransformerException
    146         */
    147        public synchronized XMLFragment transform( XMLFragment xmlDocument )
    148                                throws TransformerException {
    149
    150            XMLFragment resultFragment;
    151            try {
    152                resultFragment = transform( xmlDocument, null, null, null );
    153            } catch ( MalformedURLException e ) {
    154                LOG.logError( "Internal Error. This should not happen." );
    155                throw new TransformerException( "Internal Error. This should not happen.", e );
    156            }
    157
    158            return resultFragment;
    159        }
    160
    161        /**
    162         * Transforms the given <code>XMLFragment</code> instance.
    163         *
    164         * @param xmlDocument
    165         *            can not be null
    166         * @param target
    167         *            output stream where the result of the transformation will be written to
    168         * @throws TransformerException
    169         */
    170        public synchronized void transform( XMLFragment xmlDocument, OutputStream target )
    171                                throws TransformerException {
    172
    173            DOMSource xmlSource = new DOMSource( xmlDocument.getRootElement() );
    174            DOMSource xslSource = new DOMSource( this.getRootElement().getOwnerDocument(),
    175                                                 this.getSystemId() == null ? null : this.getSystemId().toString() );
    176            StreamResult sr = new StreamResult( target );
    177            transform( xmlSource, xslSource, sr, null, null );
    178
    179        }
    180
    181        /**
    182         * Transforms an input XML stream to an output stream using this <code>XSLTDocument</code>.
    183         *
    184         * @param input
    185         *            provides the input xml as a stream
    186         * @param target
    187         *            output stream where the result of the transformation will be written to
    188         * @throws TransformerException
    189         */
    190        public synchronized void transform( InputStream input, OutputStream target )
    191                                throws TransformerException {
    192
    193            Source xmlSource = new StreamSource( input );
    194            DOMSource xslSource = new DOMSource( this.getRootElement().getOwnerDocument(),
    195                                                 this.getSystemId() == null ? null : this.getSystemId().toString() );
    196            StreamResult sr = new StreamResult( target );
    197            transform( xmlSource, xslSource, sr, null, null );
    198
    199        }
    200
    201        /**
    202         * Transforms the XML from the given <code>InputStream</code>.
    203         * <p>
    204         * NOTE: You have to make sure that the <code>InputStream</code> provides a valid XML document.
    205         *
    206         * @param instream
    207         * @param systemId
    208         *            SystemID for the resulting <code>XMLFragment</code>
    209         * @param outputProperties
    210         *            transformation properties, may be null
    211         * @param params
    212         *            transformation parameters, may be null
    213         * @return the transformed xml file.
    214         * @throws TransformerException
    215         *             if transformation fails
    216         * @throws MalformedURLException
    217         *             if given systemId is no valid <code>URL</code>
    218         */
    219        public synchronized XMLFragment transform( InputStream instream, String systemId, Properties outputProperties,
    220                                                   Map<String, ?> params )
    221                                throws TransformerException, MalformedURLException {
    222
    223            DOMSource xslSource = new DOMSource( getRootElement().getOwnerDocument(),
    224                                                 this.getSystemId() == null ? null : this.getSystemId().toString() );
    225            Result result = transform( new StreamSource( instream ), xslSource, new DOMResult(), outputProperties, params );
    226            Document resultDocument = (Document) ( (DOMResult) result ).getNode();
    227
    228            return new XMLFragment( resultDocument, systemId );
    229        }
    230
    231        /**
    232         * Transforms the XML from the given <code>Reader</code>.
    233         * <p>
    234         * NOTE: You have to make sure that the <code>Reader</code> provides a valid XML document.
    235         *
    236         * @param reader
    237         * @param systemId
    238         *            SystemID for the resulting <code>XMLFragment</code>
    239         * @param outputProperties
    240         *            transformation properties, may be null
    241         * @param params
    242         *            transformation parameters, may be null
    243         * @return the transformed xml file.
    244         * @throws TransformerException
    245         *             if transformation fails
    246         * @throws MalformedURLException
    247         *             if given systemId is no valid <code>URL</code>
    248         */
    249        public synchronized XMLFragment transform( Reader reader, String systemId, Properties outputProperties,
    250                                                   Map<String, ?> params )
    251                                throws TransformerException, MalformedURLException {
    252
    253            DOMSource xslSource = new DOMSource( getRootElement().getOwnerDocument(),
    254                                                 this.getSystemId() == null ? null : this.getSystemId().toString() );
    255            Result result = transform( new StreamSource( reader ), xslSource, new DOMResult(), outputProperties, params );
    256            Document resultDocument = (Document) ( (DOMResult) result ).getNode();
    257
    258            return new XMLFragment( resultDocument, systemId );
    259        }
    260
    261        /**
    262         * Transforms the given XML <code>Source</code> instance using the also submitted XSLT stylesheet
    263         * <code>Source</code>.
    264         *
    265         * @param xmlSource
    266         * @param xslSource
    267         * @param result
    268         * @param outputProperties
    269         *            may be null
    270         * @param params
    271         *            may be null
    272         * @return the transformed xml file.
    273         * @throws TransformerException
    274         * @throws TransformerException
    275         */
    276        public static Result transform( Source xmlSource, Source xslSource, Result result, Properties outputProperties,
    277                                        Map<String, ?> params )
    278                                throws TransformerException {
    279
    280            try {
    281                Transformer transformer = factory.newTransformer( xslSource );
    282
    283                if ( params != null ) {
    284                    Iterator<String> it = params.keySet().iterator();
    285                    while ( it.hasNext() ) {
    286                        String key = it.next();
    287                        transformer.setParameter( key, params.get( key ) );
    288                    }
    289                }
    290                if ( outputProperties != null ) {
    291                    transformer.setOutputProperties( outputProperties );
    292                }
    293
    294                transformer.transform( xmlSource, result );
    295            } catch ( TransformerException e ) {
    296                String transformerClassName = null;
    297                String transformerFactoryClassName = factory.getClass().getName();
    298                try {
    299                    transformerClassName = factory.newTransformer().getClass().getName();
    300                } catch ( Exception e2 ) {
    301                    LOG.logError( "Error creating Transformer instance." );
    302                }
    303                String errorMsg = "XSL transformation using stylesheet with systemId '" + xslSource.getSystemId()
    304                                  + "' and xml source with systemId '" + xmlSource.getSystemId()
    305                                  + "' failed. TransformerFactory class: " + transformerFactoryClassName
    306                                  + "', Transformer class: " + transformerClassName;
    307                LOG.logError( errorMsg, e );
    308                throw new TransformerException( errorMsg, e );
    309            }
    310
    311            return result;
    312        }
    313    }