001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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 }