Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.jelly.XMLOutput |
49% |
81% |

1 |  |
     /*
2 |  |
      * Copyright 2002,2004 The Apache Software Foundation.
3 |  |
      *
4 |  |
      * Licensed under the Apache License, Version 2.0 (the "License");
5 |  |
      * you may not use this file except in compliance with the License.
6 |  |
      * You may obtain a copy of the License at
7 |  |
      *
8 |  |
      *      http://www.apache.org/licenses/LICENSE-2.0
9 |  |
      *
10 |  |
      * Unless required by applicable law or agreed to in writing, software
11 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
12 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  |
      * See the License for the specific language governing permissions and
14 |  |
      * limitations under the License.
15 |  |
      */
16 |  |
17 |  |
     package org.apache.commons.jelly;
18 |  |
19 |  |
     import java.io.IOException;
20 |  |
     import java.io.OutputStream;
21 |  |
     import java.io.UnsupportedEncodingException;
22 |  |
     import java.io.Writer;
23 |  |
24 |  |
     import org.apache.commons.logging.Log;
25 |  |
     import org.apache.commons.logging.LogFactory;
26 |  |
     import org.dom4j.io.XMLWriter;
27 |  |
     import org.xml.sax.Attributes;
28 |  |
     import org.xml.sax.ContentHandler;
29 |  |
     import org.xml.sax.Locator;
30 |  |
     import org.xml.sax.SAXException;
31 |  |
     import org.xml.sax.XMLReader;
32 |  |
     import org.xml.sax.ext.LexicalHandler;
33 |  |
     import org.xml.sax.helpers.AttributesImpl;
34 |  |
     import org.xml.sax.helpers.DefaultHandler;
35 |  |
36 |  |
     /** <p><code>XMLOutput</code> is used to output XML events
37 |  |
       * in a SAX-like manner. This also allows pipelining to be done
38 |  |
       * such as in the <a href="http://xml.apache.org/cocoon/">Cocoon</a> project.</p>
39 |  |
       *
40 |  |
       * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
41 |  |
       * @version $Revision: 155420 $
42 |  |
       */
43 |  |
44 |  |
     public class XMLOutput implements ContentHandler, LexicalHandler {
45 |  |
46 | 286 |
         protected static final String[] LEXICAL_HANDLER_NAMES =
47 |  |
             {
48 |  |
                 "http://xml.org/sax/properties/lexical-handler",
49 |  |
                 "http://xml.org/sax/handlers/LexicalHandler" };
50 |  |
51 |  |
         /** empty attributes */
52 | 286 |
         private static final Attributes EMPTY_ATTRIBUTES = new AttributesImpl();
53 |  |
54 |  |
         /** The Log to which logging calls will be made. */
55 | 572 |
         private static final Log log = LogFactory.getLog(XMLOutput.class);
56 |  |
57 |  |
         /** the default for escaping of text */
58 |  |
         private static final boolean DEFAULT_ESCAPE_TEXT = false;
59 |  |
60 |  |
         /** The SAX ContentHandler that output goes to */
61 |  |
         private ContentHandler contentHandler;
62 |  |
63 |  |
         /** The SAX LexicalHandler that output goes to */
64 |  |
         private LexicalHandler lexicalHandler;
65 |  |
66 |  |
67 | 897 |
         public XMLOutput() {
68 | 897 |
         }
69 |  |
70 | 962 |
         public XMLOutput(ContentHandler contentHandler) {
71 | 962 |
             this.contentHandler = contentHandler;
72 |  |
             // often classes will implement LexicalHandler as well
73 | 962 |
             if (contentHandler instanceof LexicalHandler) {
74 | 0 |
                 this.lexicalHandler = (LexicalHandler) contentHandler;
75 |  |
             }
76 | 962 |
         }
77 |  |
78 |  |
         public XMLOutput(
79 |  |
             ContentHandler contentHandler,
80 | 26 |
             LexicalHandler lexicalHandler) {
81 | 26 |
             this.contentHandler = contentHandler;
82 | 26 |
             this.lexicalHandler = lexicalHandler;
83 | 26 |
         }
84 |  |
85 |  |
         public String toString() {
86 | 0 |
             return super.toString()
87 |  |
                 + "[contentHandler="
88 |  |
                 + contentHandler
89 |  |
                 + ";lexicalHandler="
90 |  |
                 + lexicalHandler
91 |  |
                 + "]";
92 |  |
         }
93 |  |
94 |  |
         /**
95 |  |
          * Provides a useful hook that implementations can use to close the
96 |  |
          * underlying OutputStream or Writer
97 |  |
          */
98 |  |
         public void close() throws IOException {
99 | 0 |
         }
100 |  |
101 |  |
         public void flush() throws IOException {
102 | 11622 |
             if( contentHandler instanceof XMLWriter )
103 |  |
             {
104 | 3016 |
                 ((XMLWriter)contentHandler).flush();
105 |  |
             }
106 | 11622 |
         }
107 |  |
108 |  |
         // Static helper methods
109 |  |
         //-------------------------------------------------------------------------
110 |  |
111 |  |
         /**
112 |  |
          * Creates an XMLOutput from an existing SAX XMLReader
113 |  |
          */
114 |  |
         public static XMLOutput createXMLOutput(XMLReader xmlReader) {
115 | 0 |
             XMLOutput output = new XMLOutput(xmlReader.getContentHandler());
116 |  |
117 |  |
             // isn't it lovely what we've got to do to find the LexicalHandler... ;-)
118 | 0 |
             for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) {
119 |  |
                 try {
120 | 0 |
                     Object value = xmlReader.getProperty(LEXICAL_HANDLER_NAMES[i]);
121 | 0 |
                     if (value instanceof LexicalHandler) {
122 | 0 |
                         output.setLexicalHandler((LexicalHandler) value);
123 | 0 |
                         break;
124 |  |
                     }
125 |  |
                 }
126 | 0 |
                 catch (Exception e) {
127 |  |
                     // ignore any unsupported-operation exceptions
128 | 0 |
                     if (log.isDebugEnabled()) log.debug("error setting lexical handler properties", e);
129 | 0 |
                 }
130 |  |
             }
131 | 0 |
             return output;
132 |  |
         }
133 |  |
134 |  |
         /**
135 |  |
          * Creates a text based XMLOutput which converts all XML events into
136 |  |
          * text and writes to the underlying Writer.
137 |  |
          */
138 |  |
         public static XMLOutput createXMLOutput(Writer writer) {
139 | 169 |
             return createXMLOutput(writer, DEFAULT_ESCAPE_TEXT);
140 |  |
         }
141 |  |
142 |  |
         /**
143 |  |
          * Creates a text based XMLOutput which converts all XML events into
144 |  |
          * text and writes to the underlying Writer.
145 |  |
          *
146 |  |
          * @param writer is the writer to output to
147 |  |
          * @param escapeText is whether or not text output will be escaped. This must be true
148 |  |
          * if the underlying output is XML or could be false if the underlying output is textual.
149 |  |
          */
150 |  |
         public static XMLOutput createXMLOutput(Writer writer, boolean escapeText)
151 |  |
         {
152 | 741 |
             XMLWriter xmlWriter = new XMLWriter(writer);
153 | 741 |
             xmlWriter.setEscapeText(escapeText);
154 | 741 |
             return createXMLOutput(xmlWriter);
155 |  |
         }
156 |  |
157 |  |
         /**
158 |  |
          * Creates a text based XMLOutput which converts all XML events into
159 |  |
          * text and writes to the underlying OutputStream.
160 |  |
          */
161 |  |
         public static XMLOutput createXMLOutput(OutputStream out) throws UnsupportedEncodingException {
162 | 78 |
             return createXMLOutput(out, DEFAULT_ESCAPE_TEXT);
163 |  |
         }
164 |  |
165 |  |
         /**
166 |  |
          * Creates a text based XMLOutput which converts all XML events into
167 |  |
          * text and writes to the underlying OutputStream.
168 |  |
          *
169 |  |
          * @param out is the output stream to write
170 |  |
          * @param escapeText is whether or not text output will be escaped. This must be true
171 |  |
          * if the underlying output is XML or could be false if the underlying output is textual.
172 |  |
          */
173 |  |
         public static XMLOutput createXMLOutput(OutputStream out, boolean escapeText) throws UnsupportedEncodingException {
174 | 78 |
             XMLWriter xmlWriter = new XMLWriter(out);
175 | 78 |
             xmlWriter.setEscapeText(escapeText);
176 | 78 |
             return createXMLOutput(xmlWriter);
177 |  |
         }
178 |  |
179 |  |
         /**
180 |  |
          * returns an XMLOutput object that will discard all
181 |  |
          * tag-generated XML events.  Useful when tag output is not expected
182 |  |
          * or not significant.
183 |  |
          *
184 |  |
          * @return a no-op XMLOutput
185 |  |
          */
186 |  |
         public static XMLOutput createDummyXMLOutput() {
187 | 936 |
             return new XMLOutput(class="keyword">new DefaultHandler());
188 |  |
         }
189 |  |
190 |  |
         // Extra helper methods provided for tag authors
191 |  |
         //-------------------------------------------------------------------------
192 |  |
193 |  |
         /**
194 |  |
          * Outputs the given String as a piece of valid text in the
195 |  |
          * XML event stream.
196 |  |
          * Any special XML characters should be properly escaped.
197 |  |
          */
198 |  |
         public void write(String text) throws SAXException {
199 | 1820 |
             char[] ch = text.toCharArray();
200 | 1820 |
             characters(ch, 0, ch.length);
201 | 1820 |
         }
202 |  |
203 |  |
         /**
204 |  |
          * Outputs the given String as a piece of CDATA in the
205 |  |
          * XML event stream.
206 |  |
          */
207 |  |
         public void writeCDATA(String text) throws SAXException {
208 | 0 |
             startCDATA();
209 | 0 |
             char[] ch = text.toCharArray();
210 | 0 |
             characters(ch, 0, ch.length);
211 | 0 |
             endCDATA();
212 | 0 |
         }
213 |  |
214 |  |
         /**
215 |  |
          * Outputs a comment to the XML stream
216 |  |
          */
217 |  |
         public void writeComment(String text) throws SAXException {
218 | 0 |
             char[] ch = text.toCharArray();
219 | 0 |
             comment(ch, 0, ch.length);
220 | 0 |
         }
221 |  |
222 |  |
         /**
223 |  |
          * Helper method for outputting a start element event for an element in no namespace
224 |  |
          */
225 |  |
         public void startElement(String localName) throws SAXException {
226 | 0 |
             startElement("", localName, localName, EMPTY_ATTRIBUTES);
227 | 0 |
         }
228 |  |
229 |  |
         /**
230 |  |
          * Helper method for outputting a start element event for an element in no namespace
231 |  |
          */
232 |  |
         public void startElement(String localName, Attributes attributes) throws SAXException {
233 | 0 |
             startElement("", localName, localName, attributes);
234 | 0 |
         }
235 |  |
236 |  |
         /**
237 |  |
          * Helper method for outputting an end element event for an element in no namespace
238 |  |
          */
239 |  |
         public void endElement(String localName) throws SAXException {
240 | 0 |
             endElement("", localName, localName);
241 | 0 |
         }
242 |  |
243 |  |
244 |  |
         // ContentHandler interface
245 |  |
         //-------------------------------------------------------------------------
246 |  |
247 |  |
         /**
248 |  |
          * Receive an object for locating the origin of SAX document events.
249 |  |
          *
250 |  |
          * <p>SAX parsers are strongly encouraged (though not absolutely
251 |  |
          * required) to supply a locator: if it does so, it must supply
252 |  |
          * the locator to the application by invoking this method before
253 |  |
          * invoking any of the other methods in the ContentHandler
254 |  |
          * interface.</p>
255 |  |
          *
256 |  |
          * <p>The locator allows the application to determine the end
257 |  |
          * position of any document-related event, even if the parser is
258 |  |
          * not reporting an error.  Typically, the application will
259 |  |
          * use this information for reporting its own errors (such as
260 |  |
          * character content that does not match an application's
261 |  |
          * business rules).  The information returned by the locator
262 |  |
          * is probably not sufficient for use with a search engine.</p>
263 |  |
          *
264 |  |
          * <p>Note that the locator will return correct information only
265 |  |
          * during the invocation of the events in this interface.  The
266 |  |
          * application should not attempt to use it at any other time.</p>
267 |  |
          *
268 |  |
          * @param locator An object that can return the location of
269 |  |
          *                any SAX document event.
270 |  |
          * @see org.xml.sax.Locator
271 |  |
          */
272 |  |
         public void setDocumentLocator(Locator locator) {
273 | 0 |
             contentHandler.setDocumentLocator(locator);
274 | 0 |
         }
275 |  |
276 |  |
         /**
277 |  |
          * Receive notification of the beginning of a document.
278 |  |
          *
279 |  |
          * <p>The SAX parser will invoke this method only once, before any
280 |  |
          * other event callbacks (except for {@link #setDocumentLocator
281 |  |
          * setDocumentLocator}).</p>
282 |  |
          *
283 |  |
          * @exception org.xml.sax.SAXException Any SAX exception, possibly
284 |  |
          *            wrapping another exception.
285 |  |
          * @see #endDocument
286 |  |
          */
287 |  |
         public void startDocument() throws SAXException {
288 | 104 |
             contentHandler.startDocument();
289 | 104 |
         }
290 |  |
291 |  |
         /**
292 |  |
          * Receive notification of the end of a document.
293 |  |
          *
294 |  |
          * <p>The SAX parser will invoke this method only once, and it will
295 |  |
          * be the last method invoked during the parse.  The parser shall
296 |  |
          * not invoke this method until it has either abandoned parsing
297 |  |
          * (because of an unrecoverable error) or reached the end of
298 |  |
          * input.</p>
299 |  |
          *
300 |  |
          * @exception org.xml.sax.SAXException Any SAX exception, possibly
301 |  |
          *            wrapping another exception.
302 |  |
          * @see #startDocument
303 |  |
          */
304 |  |
         public void endDocument() throws SAXException {
305 | 104 |
             contentHandler.endDocument();
306 | 104 |
         }
307 |  |
308 |  |
         /**
309 |  |
          * Begin the scope of a prefix-URI Namespace mapping.
310 |  |
          *
311 |  |
          * <p>The information from this event is not necessary for
312 |  |
          * normal Namespace processing: the SAX XML reader will
313 |  |
          * automatically replace prefixes for element and attribute
314 |  |
          * names when the <code>http://xml.org/sax/features/namespaces</code>
315 |  |
          * feature is <var>true</var> (the default).</p>
316 |  |
          *
317 |  |
          * <p>There are cases, however, when applications need to
318 |  |
          * use prefixes in character data or in attribute values,
319 |  |
          * where they cannot safely be expanded automatically; the
320 |  |
          * start/endPrefixMapping event supplies the information
321 |  |
          * to the application to expand prefixes in those contexts
322 |  |
          * itself, if necessary.</p>
323 |  |
          *
324 |  |
          * <p>Note that start/endPrefixMapping events are not
325 |  |
          * guaranteed to be properly nested relative to each other:
326 |  |
          * all startPrefixMapping events will occur immediately before the
327 |  |
          * corresponding {@link #startElement startElement} event,
328 |  |
          * and all {@link #endPrefixMapping endPrefixMapping}
329 |  |
          * events will occur immediately after the corresponding
330 |  |
          * {@link #endElement endElement} event,
331 |  |
          * but their order is not otherwise
332 |  |
          * guaranteed.</p>
333 |  |
          *
334 |  |
          * <p>There should never be start/endPrefixMapping events for the
335 |  |
          * "xml" prefix, since it is predeclared and immutable.</p>
336 |  |
          *
337 |  |
          * @param prefix The Namespace prefix being declared.
338 |  |
          *  An empty string is used for the default element namespace,
339 |  |
          *  which has no prefix.
340 |  |
          * @param uri The Namespace URI the prefix is mapped to.
341 |  |
          * @exception org.xml.sax.SAXException The client may throw
342 |  |
          *            an exception during processing.
343 |  |
          * @see #endPrefixMapping
344 |  |
          * @see #startElement
345 |  |
          */
346 |  |
         public void startPrefixMapping(String prefix, String uri) throws SAXException {
347 | 13 |
             contentHandler.startPrefixMapping(prefix, uri);
348 | 13 |
         }
349 |  |
350 |  |
         /**
351 |  |
          * End the scope of a prefix-URI mapping.
352 |  |
          *
353 |  |
          * <p>See {@link #startPrefixMapping startPrefixMapping} for
354 |  |
          * details.  These events will always occur immediately after the
355 |  |
          * corresponding {@link #endElement endElement} event, but the order of
356 |  |
          * {@link #endPrefixMapping endPrefixMapping} events is not otherwise
357 |  |
          * guaranteed.</p>
358 |  |
          *
359 |  |
          * @param prefix The prefix that was being mapped.
360 |  |
          *  This is the empty string when a default mapping scope ends.
361 |  |
          * @exception org.xml.sax.SAXException The client may throw
362 |  |
          *            an exception during processing.
363 |  |
          * @see #startPrefixMapping
364 |  |
          * @see #endElement
365 |  |
          */
366 |  |
         public void endPrefixMapping(String prefix) throws SAXException {
367 | 13 |
             contentHandler.endPrefixMapping(prefix);
368 | 13 |
         }
369 |  |
370 |  |
         /**
371 |  |
          * Receive notification of the beginning of an element.
372 |  |
          *
373 |  |
          * <p>The Parser will invoke this method at the beginning of every
374 |  |
          * element in the XML document; there will be a corresponding
375 |  |
          * {@link #endElement endElement} event for every startElement event
376 |  |
          * (even when the element is empty). All of the element's content will be
377 |  |
          * reported, in order, before the corresponding endElement
378 |  |
          * event.</p>
379 |  |
          *
380 |  |
          * <p>This event allows up to three name components for each
381 |  |
          * element:</p>
382 |  |
          *
383 |  |
          * <ol>
384 |  |
          * <li>the Namespace URI;</li>
385 |  |
          * <li>the local name; and</li>
386 |  |
          * <li>the qualified (prefixed) name.</li>
387 |  |
          * </ol>
388 |  |
          *
389 |  |
          * <p>Any or all of these may be provided, depending on the
390 |  |
          * values of the <var>http://xml.org/sax/features/namespaces</var>
391 |  |
          * and the <var>http://xml.org/sax/features/namespace-prefixes</var>
392 |  |
          * properties:</p>
393 |  |
          *
394 |  |
          * <ul>
395 |  |
          * <li>the Namespace URI and local name are required when
396 |  |
          * the namespaces property is <var>true</var> (the default), and are
397 |  |
          * optional when the namespaces property is <var>false</var> (if one is
398 |  |
          * specified, both must be);</li>
399 |  |
          * <li>the qualified name is required when the namespace-prefixes property
400 |  |
          * is <var>true</var>, and is optional when the namespace-prefixes property
401 |  |
          * is <var>false</var> (the default).</li>
402 |  |
          * </ul>
403 |  |
          *
404 |  |
          * <p>Note that the attribute list provided will contain only
405 |  |
          * attributes with explicit values (specified or defaulted):
406 |  |
          * #IMPLIED attributes will be omitted.  The attribute list
407 |  |
          * will contain attributes used for Namespace declarations
408 |  |
          * (xmlns* attributes) only if the
409 |  |
          * <code>http://xml.org/sax/features/namespace-prefixes</code>
410 |  |
          * property is true (it is false by default, and support for a
411 |  |
          * true value is optional).</p>
412 |  |
          *
413 |  |
          * <p>Like {@link #characters characters()}, attribute values may have
414 |  |
          * characters that need more than one <code>char</code> value.  </p>
415 |  |
          *
416 |  |
          * @param uri The Namespace URI, or the empty string if the
417 |  |
          *        element has no Namespace URI or if Namespace
418 |  |
          *        processing is not being performed.
419 |  |
          * @param localName The local name (without prefix), or the
420 |  |
          *        empty string if Namespace processing is not being
421 |  |
          *        performed.
422 |  |
          * @param qName The qualified name (with prefix), or the
423 |  |
          *        empty string if qualified names are not available.
424 |  |
          * @param atts The attributes attached to the element.  If
425 |  |
          *        there are no attributes, it shall be an empty
426 |  |
          *        Attributes object.
427 |  |
          * @exception org.xml.sax.SAXException Any SAX exception, possibly
428 |  |
          *            wrapping another exception.
429 |  |
          * @see #endElement
430 |  |
          * @see org.xml.sax.Attributes
431 |  |
          */
432 |  |
         public void startElement(
433 |  |
             String uri,
434 |  |
             String localName,
435 |  |
             String qName,
436 |  |
             Attributes atts)
437 |  |
             throws SAXException {
438 | 156 |
             contentHandler.startElement(uri, localName, qName, atts);
439 | 156 |
         }
440 |  |
441 |  |
         /**
442 |  |
          * Receive notification of the end of an element.
443 |  |
          *
444 |  |
          * <p>The SAX parser will invoke this method at the end of every
445 |  |
          * element in the XML document; there will be a corresponding
446 |  |
          * {@link #startElement startElement} event for every endElement
447 |  |
          * event (even when the element is empty).</p>
448 |  |
          *
449 |  |
          * <p>For information on the names, see startElement.</p>
450 |  |
          *
451 |  |
          * @param uri The Namespace URI, or the empty string if the
452 |  |
          *        element has no Namespace URI or if Namespace
453 |  |
          *        processing is not being performed.
454 |  |
          * @param localName The local name (without prefix), or the
455 |  |
          *        empty string if Namespace processing is not being
456 |  |
          *        performed.
457 |  |
          * @param qName The qualified XML 1.0 name (with prefix), or the
458 |  |
          *        empty string if qualified names are not available.
459 |  |
          * @exception org.xml.sax.SAXException Any SAX exception, possibly
460 |  |
          *            wrapping another exception.
461 |  |
          */
462 |  |
         public void endElement(String uri, String localName, String qName)
463 |  |
             throws SAXException {
464 | 156 |
             contentHandler.endElement(uri, localName, qName);
465 | 156 |
         }
466 |  |
467 |  |
         /**
468 |  |
          * Receive notification of character data.
469 |  |
          *
470 |  |
          * <p>The Parser will call this method to report each chunk of
471 |  |
          * character data.  SAX parsers may return all contiguous character
472 |  |
          * data in a single chunk, or they may split it into several
473 |  |
          * chunks; however, all of the characters in any single event
474 |  |
          * must come from the same external entity so that the Locator
475 |  |
          * provides useful information.</p>
476 |  |
          *
477 |  |
          * <p>The application must not attempt to read from the array
478 |  |
          * outside of the specified range.</p>
479 |  |
          *
480 |  |
          * <p>Individual characters may consist of more than one Java
481 |  |
          * <code>char</code> value.  There are two important cases where this
482 |  |
          * happens, because characters can't be represented in just sixteen bits.
483 |  |
          * In one case, characters are represented in a <em>Surrogate Pair</em>,
484 |  |
          * using two special Unicode values. Such characters are in the so-called
485 |  |
          * "Astral Planes", with a code point above U+FFFF.  A second case involves
486 |  |
          * composite characters, such as a base character combining with one or
487 |  |
          * more accent characters. </p>
488 |  |
          *
489 |  |
          * <p> Your code should not assume that algorithms using
490 |  |
          * <code>char</code>-at-a-time idioms will be working in character
491 |  |
          * units; in some cases they will split characters.  This is relevant
492 |  |
          * wherever XML permits arbitrary characters, such as attribute values,
493 |  |
          * processing instruction data, and comments as well as in data reported
494 |  |
          * from this method.  It's also generally relevant whenever Java code
495 |  |
          * manipulates internationalized text; the issue isn't unique to XML.</p>
496 |  |
          *
497 |  |
          * <p>Note that some parsers will report whitespace in element
498 |  |
          * content using the {@link #ignorableWhitespace ignorableWhitespace}
499 |  |
          * method rather than this one (validating parsers <em>must</em>
500 |  |
          * do so).</p>
501 |  |
          *
502 |  |
          * @param ch The characters from the XML document.
503 |  |
          * @param start The start position in the array.
504 |  |
          * @param length The number of characters to read from the array.
505 |  |
          * @exception org.xml.sax.SAXException Any SAX exception, possibly
506 |  |
          *            wrapping another exception.
507 |  |
          * @see #ignorableWhitespace
508 |  |
          * @see org.xml.sax.Locator
509 |  |
          */
510 |  |
         public void characters(char ch[], int start, class="keyword">int length) throws SAXException {
511 | 1820 |
             contentHandler.characters(ch, start, length);
512 | 1820 |
         }
513 |  |
514 |  |
         /**
515 |  |
          * Receive notification of ignorable whitespace in element content.
516 |  |
          *
517 |  |
          * <p>Validating Parsers must use this method to report each chunk
518 |  |
          * of whitespace in element content (see the W3C XML 1.0 recommendation,
519 |  |
          * section 2.10): non-validating parsers may also use this method
520 |  |
          * if they are capable of parsing and using content models.</p>
521 |  |
          *
522 |  |
          * <p>SAX parsers may return all contiguous whitespace in a single
523 |  |
          * chunk, or they may split it into several chunks; however, all of
524 |  |
          * the characters in any single event must come from the same
525 |  |
          * external entity, so that the Locator provides useful
526 |  |
          * information.</p>
527 |  |
          *
528 |  |
          * <p>The application must not attempt to read from the array
529 |  |
          * outside of the specified range.</p>
530 |  |
          *
531 |  |
          * @param ch The characters from the XML document.
532 |  |
          * @param start The start position in the array.
533 |  |
          * @param length The number of characters to read from the array.
534 |  |
          * @exception org.xml.sax.SAXException Any SAX exception, possibly
535 |  |
          *            wrapping another exception.
536 |  |
          * @see #characters
537 |  |
          */
538 |  |
         public void ignorableWhitespace(char ch[], int start, class="keyword">int length)
539 |  |
             throws SAXException {
540 | 0 |
             contentHandler.ignorableWhitespace(ch, start, length);
541 | 0 |
         }
542 |  |
543 |  |
         /**
544 |  |
          * Receive notification of a processing instruction.
545 |  |
          *
546 |  |
          * <p>The Parser will invoke this method once for each processing
547 |  |
          * instruction found: note that processing instructions may occur
548 |  |
          * before or after the main document element.</p>
549 |  |
          *
550 |  |
          * <p>A SAX parser must never report an XML declaration (XML 1.0,
551 |  |
          * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
552 |  |
          * using this method.</p>
553 |  |
          *
554 |  |
          * <p>Like {@link #characters characters()}, processing instruction
555 |  |
          * data may have characters that need more than one <code>char</code>
556 |  |
          * value. </p>
557 |  |
          *
558 |  |
          * @param target The processing instruction target.
559 |  |
          * @param data The processing instruction data, or null if
560 |  |
          *        none was supplied.  The data does not include any
561 |  |
          *        whitespace separating it from the target.
562 |  |
          * @exception org.xml.sax.SAXException Any SAX exception, possibly
563 |  |
          *            wrapping another exception.
564 |  |
          */
565 |  |
         public void processingInstruction(String target, String data)
566 |  |
             throws SAXException {
567 | 0 |
             contentHandler.processingInstruction(target, data);
568 | 0 |
         }
569 |  |
570 |  |
         /**
571 |  |
          * Receive notification of a skipped entity.
572 |  |
          * This is not called for entity references within markup constructs
573 |  |
          * such as element start tags or markup declarations.  (The XML
574 |  |
          * recommendation requires reporting skipped external entities.
575 |  |
          * SAX also reports internal entity expansion/non-expansion, except
576 |  |
          * within markup constructs.)
577 |  |
          *
578 |  |
          * <p>The Parser will invoke this method each time the entity is
579 |  |
          * skipped.  Non-validating processors may skip entities if they
580 |  |
          * have not seen the declarations (because, for example, the
581 |  |
          * entity was declared in an external DTD subset).  All processors
582 |  |
          * may skip external entities, depending on the values of the
583 |  |
          * <code>http://xml.org/sax/features/external-general-entities</code>
584 |  |
          * and the
585 |  |
          * <code>http://xml.org/sax/features/external-parameter-entities</code>
586 |  |
          * properties.</p>
587 |  |
          *
588 |  |
          * @param name The name of the skipped entity.  If it is a
589 |  |
          *        parameter entity, the name will begin with '%', and if
590 |  |
          *        it is the external DTD subset, it will be the string
591 |  |
          *        "[dtd]".
592 |  |
          * @exception org.xml.sax.SAXException Any SAX exception, possibly
593 |  |
          *            wrapping another exception.
594 |  |
          */
595 |  |
         public void skippedEntity(String name) throws SAXException {
596 | 0 |
             contentHandler.skippedEntity(name);
597 | 0 |
         }
598 |  |
599 |  |
600 |  |
         // Lexical Handler interface
601 |  |
         //-------------------------------------------------------------------------
602 |  |
603 |  |
         /**
604 |  |
          * Report the start of DTD declarations, if any.
605 |  |
          *
606 |  |
          * <p>This method is intended to report the beginning of the
607 |  |
          * DOCTYPE declaration; if the document has no DOCTYPE declaration,
608 |  |
          * this method will not be invoked.</p>
609 |  |
          *
610 |  |
          * <p>All declarations reported through
611 |  |
          * {@link org.xml.sax.DTDHandler DTDHandler} or
612 |  |
          * {@link org.xml.sax.ext.DeclHandler DeclHandler} events must appear
613 |  |
          * between the startDTD and {@link #endDTD endDTD} events.
614 |  |
          * Declarations are assumed to belong to the internal DTD subset
615 |  |
          * unless they appear between {@link #startEntity startEntity}
616 |  |
          * and {@link #endEntity endEntity} events.  Comments and
617 |  |
          * processing instructions from the DTD should also be reported
618 |  |
          * between the startDTD and endDTD events, in their original
619 |  |
          * order of (logical) occurrence; they are not required to
620 |  |
          * appear in their correct locations relative to DTDHandler
621 |  |
          * or DeclHandler events, however.</p>
622 |  |
          *
623 |  |
          * <p>Note that the start/endDTD events will appear within
624 |  |
          * the start/endDocument events from ContentHandler and
625 |  |
          * before the first
626 |  |
          * {@link org.xml.sax.ContentHandler#startElement startElement}
627 |  |
          * event.</p>
628 |  |
          *
629 |  |
          * @param name The document type name.
630 |  |
          * @param publicId The declared public identifier for the
631 |  |
          *        external DTD subset, or null if none was declared.
632 |  |
          * @param systemId The declared system identifier for the
633 |  |
          *        external DTD subset, or null if none was declared.
634 |  |
          *        (Note that this is not resolved against the document
635 |  |
          *        base URI.)
636 |  |
          * @exception SAXException The application may raise an
637 |  |
          *            exception.
638 |  |
          * @see #endDTD
639 |  |
          * @see #startEntity
640 |  |
          */
641 |  |
         public void startDTD(String name, String class="keyword">publicId, String systemId)
642 |  |
             throws SAXException {
643 | 0 |
             if (lexicalHandler != null) {
644 | 0 |
                 lexicalHandler.startDTD(name, publicId, systemId);
645 |  |
             }
646 | 0 |
         }
647 |  |
648 |  |
         /**
649 |  |
          * Report the end of DTD declarations.
650 |  |
          *
651 |  |
          * <p>This method is intended to report the end of the
652 |  |
          * DOCTYPE declaration; if the document has no DOCTYPE declaration,
653 |  |
          * this method will not be invoked.</p>
654 |  |
          *
655 |  |
          * @exception SAXException The application may raise an exception.
656 |  |
          * @see #startDTD
657 |  |
          */
658 |  |
         public void endDTD() throws SAXException {
659 | 0 |
             if (lexicalHandler != null) {
660 | 0 |
                 lexicalHandler.endDTD();
661 |  |
             }
662 | 0 |
         }
663 |  |
664 |  |
         /**
665 |  |
          * Report the beginning of some internal and external XML entities.
666 |  |
          *
667 |  |
          * <p>The reporting of parameter entities (including
668 |  |
          * the external DTD subset) is optional, and SAX2 drivers that
669 |  |
          * report LexicalHandler events may not implement it; you can use the
670 |  |
          * <code
671 |  |
          * >http://xml.org/sax/features/lexical-handler/parameter-entities</code>
672 |  |
          * feature to query or control the reporting of parameter entities.</p>
673 |  |
          *
674 |  |
          * <p>General entities are reported with their regular names,
675 |  |
          * parameter entities have '%' prepended to their names, and
676 |  |
          * the external DTD subset has the pseudo-entity name "[dtd]".</p>
677 |  |
          *
678 |  |
          * <p>When a SAX2 driver is providing these events, all other
679 |  |
          * events must be properly nested within start/end entity
680 |  |
          * events.  There is no additional requirement that events from
681 |  |
          * {@link org.xml.sax.ext.DeclHandler DeclHandler} or
682 |  |
          * {@link org.xml.sax.DTDHandler DTDHandler} be properly ordered.</p>
683 |  |
          *
684 |  |
          * <p>Note that skipped entities will be reported through the
685 |  |
          * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
686 |  |
          * event, which is part of the ContentHandler interface.</p>
687 |  |
          *
688 |  |
          * <p>Because of the streaming event model that SAX uses, some
689 |  |
          * entity boundaries cannot be reported under any
690 |  |
          * circumstances:</p>
691 |  |
          *
692 |  |
          * <ul>
693 |  |
          * <li>general entities within attribute values</li>
694 |  |
          * <li>parameter entities within declarations</li>
695 |  |
          * </ul>
696 |  |
          *
697 |  |
          * <p>These will be silently expanded, with no indication of where
698 |  |
          * the original entity boundaries were.</p>
699 |  |
          *
700 |  |
          * <p>Note also that the boundaries of character references (which
701 |  |
          * are not really entities anyway) are not reported.</p>
702 |  |
          *
703 |  |
          * <p>All start/endEntity events must be properly nested.
704 |  |
          *
705 |  |
          * @param name The name of the entity.  If it is a parameter
706 |  |
          *        entity, the name will begin with '%', and if it is the
707 |  |
          *        external DTD subset, it will be "[dtd]".
708 |  |
          * @exception SAXException The application may raise an exception.
709 |  |
          * @see #endEntity
710 |  |
          * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
711 |  |
          * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
712 |  |
          */
713 |  |
         public void startEntity(String name) throws SAXException {
714 | 0 |
             if (lexicalHandler != null) {
715 | 0 |
                 lexicalHandler.startEntity(name);
716 |  |
             }
717 | 0 |
         }
718 |  |
719 |  |
         /**
720 |  |
          * Report the end of an entity.
721 |  |
          *
722 |  |
          * @param name The name of the entity that is ending.
723 |  |
          * @exception SAXException The application may raise an exception.
724 |  |
          * @see #startEntity
725 |  |
          */
726 |  |
         public void endEntity(String name) throws SAXException {
727 | 0 |
             if (lexicalHandler != null) {
728 | 0 |
                 lexicalHandler.endEntity(name);
729 |  |
             }
730 | 0 |
         }
731 |  |
732 |  |
         /**
733 |  |
          * Report the start of a CDATA section.
734 |  |
          *
735 |  |
          * <p>The contents of the CDATA section will be reported through
736 |  |
          * the regular {@link org.xml.sax.ContentHandler#characters
737 |  |
          * characters} event; this event is intended only to report
738 |  |
          * the boundary.</p>
739 |  |
          *
740 |  |
          * @exception SAXException The application may raise an exception.
741 |  |
          * @see #endCDATA
742 |  |
          */
743 |  |
         public void startCDATA() throws SAXException {
744 | 0 |
             if (lexicalHandler != null) {
745 | 0 |
                 lexicalHandler.startCDATA();
746 |  |
             }
747 | 0 |
         }
748 |  |
749 |  |
         /**
750 |  |
          * Report the end of a CDATA section.
751 |  |
          *
752 |  |
          * @exception SAXException The application may raise an exception.
753 |  |
          * @see #startCDATA
754 |  |
          */
755 |  |
         public void endCDATA() throws SAXException {
756 | 0 |
             if (lexicalHandler != null) {
757 | 0 |
                 lexicalHandler.endCDATA();
758 |  |
             }
759 | 0 |
         }
760 |  |
761 |  |
         /**
762 |  |
          * Report an XML comment anywhere in the document.
763 |  |
          *
764 |  |
          * <p>This callback will be used for comments inside or outside the
765 |  |
          * document element, including comments in the external DTD
766 |  |
          * subset (if read).  Comments in the DTD must be properly
767 |  |
          * nested inside start/endDTD and start/endEntity events (if
768 |  |
          * used).</p>
769 |  |
          *
770 |  |
          * @param ch An array holding the characters in the comment.
771 |  |
          * @param start The starting position in the array.
772 |  |
          * @param length The number of characters to use from the array.
773 |  |
          * @exception SAXException The application may raise an exception.
774 |  |
          */
775 |  |
         public void comment(char ch[], int start, class="keyword">int length) throws SAXException {
776 | 0 |
             if (lexicalHandler != null) {
777 | 0 |
                 lexicalHandler.comment(ch, start, length);
778 |  |
             }
779 | 0 |
         }
780 |  |
781 |  |
         /** Pass data through the pipline.
782 |  |
           * By default, this call is ignored.
783 |  |
           * Subclasses are invited to use this as a way for children tags to
784 |  |
           * pass data to their parent.
785 |  |
           *
786 |  |
           * @param object the data to pass
787 |  |
           * @exception SAXException The application may raise an exception.
788 |  |
           */
789 |  |
         public void objectData(Object object) throws SAXException {
790 | 520 |
             if(contentHandler instanceof XMLOutput)
791 | 0 |
                 ((XMLOutput) contentHandler).objectData(object);
792 |  |
             else {
793 | 520 |
                 if(object!=null) {
794 | 520 |
                     String output=object.toString();
795 | 520 |
                     write(output);
796 | 520 |
                 } else {
797 |  |
                     // we could have a "configurable null-toString"...
798 | 0 |
                     write("null");
799 |  |
                 }
800 |  |
             }
801 | 520 |
         }
802 |  |
803 |  |
         // Properties
804 |  |
         //-------------------------------------------------------------------------
805 |  |
         /**
806 |  |
          * @return the SAX ContentHandler to use to pipe SAX events into
807 |  |
          */
808 |  |
         public ContentHandler getContentHandler() {
809 | 78 |
             return contentHandler;
810 |  |
         }
811 |  |
812 |  |
         /**
813 |  |
          * Sets the SAX ContentHandler to pipe SAX events into
814 |  |
          *
815 |  |
          * @param contentHandler is the new ContentHandler to use.
816 |  |
          *      This value cannot be null.
817 |  |
          */
818 |  |
         public void setContentHandler(ContentHandler contentHandler) {
819 | 975 |
             if (contentHandler == null) {
820 | 0 |
                 throw new NullPointerException("ContentHandler cannot be null!");
821 |  |
             }
822 | 975 |
             this.contentHandler = contentHandler;
823 | 975 |
         }
824 |  |
825 |  |
         /**
826 |  |
          * @return the SAX LexicalHandler to use to pipe SAX events into
827 |  |
          */
828 |  |
         public LexicalHandler getLexicalHandler() {
829 | 0 |
             return lexicalHandler;
830 |  |
         }
831 |  |
832 |  |
         /**
833 |  |
          * Sets the SAX LexicalHandler to pipe SAX events into
834 |  |
          *
835 |  |
          * @param lexicalHandler is the new LexicalHandler to use.
836 |  |
          *      This value can be null.
837 |  |
          */
838 |  |
         public void setLexicalHandler(LexicalHandler lexicalHandler) {
839 | 897 |
             this.lexicalHandler = lexicalHandler;
840 | 897 |
         }
841 |  |
842 |  |
         // Implementation methods
843 |  |
         //-------------------------------------------------------------------------
844 |  |
         /**
845 |  |
          * Factory method to create a new XMLOutput from an XMLWriter
846 |  |
          */
847 |  |
         protected static XMLOutput createXMLOutput(final XMLWriter xmlWriter) {
848 | 819 |
             XMLOutput answer = new XMLOutput() {
849 |  |
                 public void close() throws IOException {
850 |  |
                     xmlWriter.close();
851 |  |
                 }
852 |  |
             };
853 | 819 |
             answer.setContentHandler(xmlWriter);
854 | 819 |
             answer.setLexicalHandler(xmlWriter);
855 | 819 |
             return answer;
856 |  |
         }
857 |  |
858 |  |
     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.