0
|
1 /*--
|
|
2
|
|
3 $Id: JDOMSource.java,v 1.20 2007/11/10 05:29:02 jhunter Exp $
|
|
4
|
|
5 Copyright (C) 2001-2007 Jason Hunter & Brett McLaughlin.
|
|
6 All rights reserved.
|
|
7
|
|
8 Redistribution and use in source and binary forms, with or without
|
|
9 modification, are permitted provided that the following conditions
|
|
10 are met:
|
|
11
|
|
12 1. Redistributions of source code must retain the above copyright
|
|
13 notice, this list of conditions, and the following disclaimer.
|
|
14
|
|
15 2. Redistributions in binary form must reproduce the above copyright
|
|
16 notice, this list of conditions, and the disclaimer that follows
|
|
17 these conditions in the documentation and/or other materials
|
|
18 provided with the distribution.
|
|
19
|
|
20 3. The name "JDOM" must not be used to endorse or promote products
|
|
21 derived from this software without prior written permission. For
|
|
22 written permission, please contact <request_AT_jdom_DOT_org>.
|
|
23
|
|
24 4. Products derived from this software may not be called "JDOM", nor
|
|
25 may "JDOM" appear in their name, without prior written permission
|
|
26 from the JDOM Project Management <request_AT_jdom_DOT_org>.
|
|
27
|
|
28 In addition, we request (but do not require) that you include in the
|
|
29 end-user documentation provided with the redistribution and/or in the
|
|
30 software itself an acknowledgement equivalent to the following:
|
|
31 "This product includes software developed by the
|
|
32 JDOM Project (http://www.jdom.org/)."
|
|
33 Alternatively, the acknowledgment may be graphical using the logos
|
|
34 available at http://www.jdom.org/images/logos.
|
|
35
|
|
36 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
|
37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
38 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
39 DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
|
|
40 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
43 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
46 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
47 SUCH DAMAGE.
|
|
48
|
|
49 This software consists of voluntary contributions made by many
|
|
50 individuals on behalf of the JDOM Project and was originally
|
|
51 created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
|
|
52 Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
|
|
53 on the JDOM Project, please see <http://www.jdom.org/>.
|
|
54
|
|
55 */
|
|
56
|
|
57 package org.jdom.transform;
|
|
58
|
|
59 import java.io.*;
|
|
60 import java.util.*;
|
|
61
|
|
62 import javax.xml.transform.sax.*;
|
|
63
|
|
64 import org.jdom.*;
|
|
65 import org.jdom.output.*;
|
|
66 import org.xml.sax.*;
|
|
67
|
|
68 /**
|
|
69 * A holder for an XML Transformation source: a Document, Element, or list of
|
|
70 * nodes.
|
|
71 * <p>
|
|
72 * The is provides input to a
|
|
73 * {@link javax.xml.transform.Transformer JAXP TrAX Transformer}.
|
|
74 * <p>
|
|
75 * The following example shows how to apply an XSL Transformation
|
|
76 * to a JDOM document and get the transformation result in the form
|
|
77 * of a list of JDOM nodes:
|
|
78 * <pre><code>
|
|
79 * public static List transform(Document doc, String stylesheet)
|
|
80 * throws JDOMException {
|
|
81 * try {
|
|
82 * Transformer transformer = TransformerFactory.newInstance()
|
|
83 * .newTransformer(new StreamSource(stylesheet));
|
|
84 * JDOMSource in = new JDOMSource(doc);
|
|
85 * JDOMResult out = new JDOMResult();
|
|
86 * transformer.transform(in, out);
|
|
87 * return out.getResult();
|
|
88 * }
|
|
89 * catch (TransformerException e) {
|
|
90 * throw new JDOMException("XSLT Transformation failed", e);
|
|
91 * }
|
|
92 * }
|
|
93 * </code></pre>
|
|
94 *
|
|
95 * @see org.jdom.transform.JDOMResult
|
|
96 *
|
|
97 * @version $Revision: 1.20 $, $Date: 2007/11/10 05:29:02 $
|
|
98 * @author Laurent Bihanic
|
|
99 * @author Jason Hunter
|
|
100 */
|
|
101 public class JDOMSource extends SAXSource {
|
|
102
|
|
103 private static final String CVS_ID =
|
|
104 "@(#) $RCSfile: JDOMSource.java,v $ $Revision: 1.20 $ $Date: 2007/11/10 05:29:02 $ $Name: jdom_1_1_1 $";
|
|
105
|
|
106 /**
|
|
107 * If {@link javax.xml.transform.TransformerFactory#getFeature}
|
|
108 * returns <code>true</code> when passed this value as an
|
|
109 * argument, the Transformer natively supports JDOM.
|
|
110 * <p>
|
|
111 * <strong>Note</strong>: This implementation does not override
|
|
112 * the {@link SAXSource#FEATURE} value defined by its superclass
|
|
113 * to be considered as a SAXSource by Transformer implementations
|
|
114 * not natively supporting JDOM.
|
|
115 * </p>
|
|
116 */
|
|
117 public final static String JDOM_FEATURE =
|
|
118 "http://org.jdom.transform.JDOMSource/feature";
|
|
119
|
|
120 /**
|
|
121 * The XMLReader object associated to this source or
|
|
122 * <code>null</code> if no XMLReader has yet been requested.
|
|
123 *
|
|
124 * @see #getXMLReader
|
|
125 */
|
|
126 private XMLReader xmlReader = null;
|
|
127
|
|
128 /**
|
|
129 * Optional entity resolver associated to the source of
|
|
130 * this document or <code>null</code> if no EntityResolver
|
|
131 * was supplied with this JDOMSource.
|
|
132 *
|
|
133 * @see #buildDocumentReader()
|
|
134 */
|
|
135 private EntityResolver resolver = null;
|
|
136
|
|
137 /**
|
|
138 * Creates a JDOM TrAX source wrapping a JDOM document.
|
|
139 *
|
|
140 * @param source the JDOM document to use as source for the
|
|
141 * transformations
|
|
142 *
|
|
143 * @throws IllegalArgumentException if <code>source</code> is
|
|
144 * <code>null</code>.
|
|
145 */
|
|
146 public JDOMSource(Document source) {
|
|
147 setDocument(source);
|
|
148 }
|
|
149
|
|
150 /**
|
|
151 * Creates a JDOM TrAX source wrapping a list of JDOM nodes.
|
|
152 *
|
|
153 * @param source the JDOM nodes to use as source for the
|
|
154 * transformations
|
|
155 *
|
|
156 * @throws IllegalArgumentException if <code>source</code> is
|
|
157 * <code>null</code>.
|
|
158 */
|
|
159 public JDOMSource(List source) {
|
|
160 setNodes(source);
|
|
161 }
|
|
162
|
|
163 /**
|
|
164 * Creates a JDOM TrAX source wrapping a JDOM element.
|
|
165 *
|
|
166 * @param source the JDOM element to use as source for the
|
|
167 * transformations
|
|
168 *
|
|
169 * @throws IllegalArgumentException if <code>source</code> is
|
|
170 * <code>null</code>.
|
|
171 */
|
|
172 public JDOMSource(Element source) {
|
|
173 List nodes = new ArrayList();
|
|
174 nodes.add(source);
|
|
175
|
|
176 setNodes(nodes);
|
|
177 }
|
|
178
|
|
179 /**
|
|
180 * Creates a JDOM TrAX source wrapping a JDOM element with an
|
|
181 * associated EntityResolver to resolve external entities.
|
|
182 *
|
|
183 * @param source The JDOM Element to use as source for the
|
|
184 * transformations
|
|
185 *
|
|
186 * @param resolver Entity resolver to use for the source
|
|
187 * transformation
|
|
188 *
|
|
189 * @throws IllegalArgumentException if<code>source</code> is
|
|
190 * <code>null</code>
|
|
191 */
|
|
192 public JDOMSource(Document source, EntityResolver resolver) {
|
|
193 setDocument(source);
|
|
194 this.resolver = resolver;
|
|
195 }
|
|
196
|
|
197 /**
|
|
198 * Sets the source document used by this TrAX source.
|
|
199 *
|
|
200 * @param source the JDOM document to use as source for the
|
|
201 * transformations
|
|
202 *
|
|
203 * @throws IllegalArgumentException if <code>source</code> is
|
|
204 * <code>null</code>.
|
|
205 *
|
|
206 * @see #getDocument
|
|
207 */
|
|
208 public void setDocument(Document source) {
|
|
209 super.setInputSource(new JDOMInputSource(source));
|
|
210 }
|
|
211
|
|
212 /**
|
|
213 * Returns the source document used by this TrAX source.
|
|
214 *
|
|
215 * @return the source document used by this TrAX source or
|
|
216 * <code>null</code> if the source is a node list.
|
|
217 *
|
|
218 * @see #setDocument
|
|
219 */
|
|
220 public Document getDocument() {
|
|
221 Object src = ((JDOMInputSource)getInputSource()).getSource();
|
|
222 Document doc = null;
|
|
223
|
|
224 if (src instanceof Document) {
|
|
225 doc = (Document)src;
|
|
226 }
|
|
227 return doc;
|
|
228 }
|
|
229
|
|
230 /**
|
|
231 * Sets the source node list used by this TrAX source.
|
|
232 *
|
|
233 * @param source the JDOM nodes to use as source for the
|
|
234 * transformations
|
|
235 *
|
|
236 * @throws IllegalArgumentException if <code>source</code> is
|
|
237 * <code>null</code>.
|
|
238 *
|
|
239 * @see #getNodes
|
|
240 */
|
|
241 public void setNodes(List source) {
|
|
242 super.setInputSource(new JDOMInputSource(source));
|
|
243 }
|
|
244
|
|
245 /**
|
|
246 * Returns the source node list used by this TrAX source.
|
|
247 *
|
|
248 * @return the source node list used by this TrAX source or
|
|
249 * <code>null</code> if the source is a JDOM document.
|
|
250 *
|
|
251 * @see #setDocument
|
|
252 */
|
|
253 public List getNodes() {
|
|
254 Object src = ((JDOMInputSource)getInputSource()).getSource();
|
|
255 List nodes = null;
|
|
256
|
|
257 if (src instanceof List) {
|
|
258 nodes = (List)src;
|
|
259 }
|
|
260 return nodes;
|
|
261 }
|
|
262
|
|
263
|
|
264 //-------------------------------------------------------------------------
|
|
265 // SAXSource overwritten methods
|
|
266 //-------------------------------------------------------------------------
|
|
267
|
|
268 /**
|
|
269 * Sets the SAX InputSource to be used for the Source.
|
|
270 * <p>
|
|
271 * As this implementation only supports JDOM document as data
|
|
272 * source, this method always throws an
|
|
273 * {@link UnsupportedOperationException}.
|
|
274 * </p>
|
|
275 *
|
|
276 * @param inputSource a valid InputSource reference.
|
|
277 *
|
|
278 * @throws UnsupportedOperationException always!
|
|
279 */
|
|
280 public void setInputSource(InputSource inputSource)
|
|
281 throws UnsupportedOperationException {
|
|
282 throw new UnsupportedOperationException();
|
|
283 }
|
|
284
|
|
285 /**
|
|
286 * Set the XMLReader to be used for the Source.
|
|
287 * <p>
|
|
288 * As this implementation only supports JDOM document as data
|
|
289 * source, this method throws an
|
|
290 * {@link UnsupportedOperationException} if the provided reader
|
|
291 * object does not implement the SAX {@link XMLFilter}
|
|
292 * interface. Otherwise, the JDOM document reader will be
|
|
293 * attached as parent of the filter chain.</p>
|
|
294 *
|
|
295 * @param reader a valid XMLReader or XMLFilter reference.
|
|
296 *
|
|
297 * @throws UnsupportedOperationException if <code>reader</code>
|
|
298 * is not a SAX
|
|
299 * {@link XMLFilter}.
|
|
300 * @see #getXMLReader
|
|
301 */
|
|
302 public void setXMLReader(XMLReader reader)
|
|
303 throws UnsupportedOperationException {
|
|
304 if (reader instanceof XMLFilter) {
|
|
305 // Connect the filter chain to a document reader.
|
|
306 XMLFilter filter = (XMLFilter)reader;
|
|
307 while (filter.getParent() instanceof XMLFilter) {
|
|
308 filter = (XMLFilter)(filter.getParent());
|
|
309 }
|
|
310 filter.setParent(buildDocumentReader());
|
|
311
|
|
312 // Read XML data from filter chain.
|
|
313 this.xmlReader = reader;
|
|
314 }
|
|
315 else {
|
|
316 throw new UnsupportedOperationException();
|
|
317 }
|
|
318 }
|
|
319
|
|
320 /**
|
|
321 * Returns the XMLReader to be used for the Source.
|
|
322 * <p>
|
|
323 * This implementation returns a specific XMLReader reading
|
|
324 * the XML data from the source JDOM document.
|
|
325 * </p>
|
|
326 *
|
|
327 * @return an XMLReader reading the XML data from the source
|
|
328 * JDOM document.
|
|
329 */
|
|
330 public XMLReader getXMLReader() {
|
|
331 if (this.xmlReader == null) {
|
|
332 this.xmlReader = buildDocumentReader();
|
|
333 }
|
|
334 return this.xmlReader;
|
|
335 }
|
|
336
|
|
337 /**
|
|
338 * Build an XMLReader to be used for the source. This will
|
|
339 * create a new instance of DocumentReader with an
|
|
340 * EntityResolver instance if available.
|
|
341 *
|
|
342 * @return XMLReader reading the XML data from the source
|
|
343 * JDOM document with an optional EntityResolver
|
|
344 */
|
|
345 private XMLReader buildDocumentReader() {
|
|
346 DocumentReader reader = new DocumentReader();
|
|
347 if (resolver != null)
|
|
348 reader.setEntityResolver(resolver);
|
|
349 return reader;
|
|
350 }
|
|
351
|
|
352 //=========================================================================
|
|
353 // JDOMInputSource nested class
|
|
354 //=========================================================================
|
|
355
|
|
356 /**
|
|
357 * A subclass of the SAX InputSource interface that wraps a JDOM
|
|
358 * Document.
|
|
359 * <p>
|
|
360 * This class is nested in JDOMSource as it is not intented to
|
|
361 * be used independently of its friend: DocumentReader.
|
|
362 * </p>
|
|
363 *
|
|
364 * @see org.jdom.Document
|
|
365 */
|
|
366 private static class JDOMInputSource extends InputSource {
|
|
367 /**
|
|
368 * The source as a JDOM document or a list of JDOM nodes.
|
|
369 */
|
|
370 private Object source = null;
|
|
371
|
|
372 /**
|
|
373 * Builds a InputSource wrapping the specified JDOM Document.
|
|
374 *
|
|
375 * @param document the source document.
|
|
376 */
|
|
377 public JDOMInputSource(Document document) {
|
|
378 this.source = document;
|
|
379 }
|
|
380
|
|
381 /**
|
|
382 * Builds a InputSource wrapping a list of JDOM nodes.
|
|
383 *
|
|
384 * @param nodes the source JDOM nodes.
|
|
385 */
|
|
386 public JDOMInputSource(List nodes) {
|
|
387 this.source = nodes;
|
|
388 }
|
|
389
|
|
390 /**
|
|
391 * Returns the source.
|
|
392 *
|
|
393 * @return the source as a JDOM document or a list of JDOM nodes.
|
|
394 */
|
|
395 public Object getSource() {
|
|
396 return source;
|
|
397 }
|
|
398
|
|
399 //-------------------------------------------------------------------------
|
|
400 // InputSource overwritten methods
|
|
401 //-------------------------------------------------------------------------
|
|
402
|
|
403 /**
|
|
404 * Sets the character stream for this input source.
|
|
405 * <p>
|
|
406 * This implementation always throws an
|
|
407 * {@link UnsupportedOperationException} as the only source
|
|
408 * stream supported is the source JDOM document.
|
|
409 * </p>
|
|
410 *
|
|
411 * @param characterStream a character stream containing
|
|
412 * an XML document.
|
|
413 *
|
|
414 * @throws UnsupportedOperationException always!
|
|
415 */
|
|
416 public void setCharacterStream(Reader characterStream)
|
|
417 throws UnsupportedOperationException {
|
|
418 throw new UnsupportedOperationException();
|
|
419 }
|
|
420
|
|
421 /**
|
|
422 * Gets the character stream for this input source.
|
|
423 * <p>
|
|
424 * Note that this method is only provided to make this
|
|
425 * InputSource implementation acceptable by any XML
|
|
426 * parser. As it generates an in-memory string representation
|
|
427 * of the JDOM document, it is quite inefficient from both
|
|
428 * speed and memory consumption points of view.
|
|
429 * </p>
|
|
430 *
|
|
431 * @return a Reader to a string representation of the
|
|
432 * source JDOM document.
|
|
433 */
|
|
434 public Reader getCharacterStream() {
|
|
435 Object src = this.getSource();
|
|
436 Reader reader = null;
|
|
437
|
|
438 if (src instanceof Document) {
|
|
439 // Get an in-memory string representation of the document
|
|
440 // and return a reader on it.
|
|
441 reader = new StringReader(
|
|
442 new XMLOutputter().outputString((Document)src));
|
|
443 }
|
|
444 else {
|
|
445 if (src instanceof List) {
|
|
446 reader = new StringReader(
|
|
447 new XMLOutputter().outputString((List)src));
|
|
448 }
|
|
449 // Else: No source, no reader!
|
|
450 }
|
|
451 return reader;
|
|
452 }
|
|
453 }
|
|
454
|
|
455 //=========================================================================
|
|
456 // DocumentReader nested class
|
|
457 //=========================================================================
|
|
458
|
|
459 /**
|
|
460 * An implementation of the SAX2 XMLReader interface that presents
|
|
461 * a SAX view of a JDOM Document. The actual generation of the
|
|
462 * SAX events is delegated to JDOM's SAXOutputter.
|
|
463 *
|
|
464 * @see org.jdom.Document
|
|
465 * @see org.jdom.output.SAXOutputter
|
|
466 */
|
|
467 private static class DocumentReader extends SAXOutputter
|
|
468 implements XMLReader {
|
|
469 /**
|
|
470 * Public default constructor.
|
|
471 */
|
|
472 public DocumentReader() {
|
|
473 super();
|
|
474 }
|
|
475
|
|
476 //----------------------------------------------------------------------
|
|
477 // SAX XMLReader interface support
|
|
478 //----------------------------------------------------------------------
|
|
479
|
|
480 /**
|
|
481 * Parses an XML document from a system identifier (URI).
|
|
482 * <p>
|
|
483 * This implementation does not support reading XML data from
|
|
484 * system identifiers, only from JDOM documents. Hence,
|
|
485 * this method always throws a {@link SAXNotSupportedException}.
|
|
486 * </p>
|
|
487 *
|
|
488 * @param systemId the system identifier (URI).
|
|
489 *
|
|
490 * @throws SAXNotSupportedException always!
|
|
491 */
|
|
492 public void parse(String systemId) throws SAXNotSupportedException {
|
|
493 throw new SAXNotSupportedException(
|
|
494 "Only JDOM Documents are supported as input");
|
|
495 }
|
|
496
|
|
497 /**
|
|
498 * Parses an XML document.
|
|
499 * <p>
|
|
500 * The methods accepts only <code>JDOMInputSource</code>s
|
|
501 * instances as input sources.
|
|
502 * </p>
|
|
503 *
|
|
504 * @param input the input source for the top-level of the
|
|
505 * XML document.
|
|
506 *
|
|
507 * @throws SAXException any SAX exception,
|
|
508 * possibly wrapping
|
|
509 * another exception.
|
|
510 * @throws SAXNotSupportedException if the input source does
|
|
511 * not wrap a JDOM document.
|
|
512 */
|
|
513 public void parse(InputSource input) throws SAXException {
|
|
514 if (input instanceof JDOMInputSource) {
|
|
515 try {
|
|
516 Object source = ((JDOMInputSource)input).getSource();
|
|
517 if (source instanceof Document) {
|
|
518 this.output((Document)source);
|
|
519 }
|
|
520 else {
|
|
521 this.output((List)source);
|
|
522 }
|
|
523 }
|
|
524 catch (JDOMException e) {
|
|
525 throw new SAXException(e.getMessage(), e);
|
|
526 }
|
|
527 }
|
|
528 else {
|
|
529 throw new SAXNotSupportedException(
|
|
530 "Only JDOM Documents are supported as input");
|
|
531 }
|
|
532 }
|
|
533 }
|
|
534 }
|
|
535
|