source: Ballon/out/artifacts/geisa_artifact/WEB-INF/lib/mysql-connector-java-5.1.21/src/com/mysql/jdbc/JDBC4MysqlSQLXML.java @ 848

Last change on this file since 848 was 766, checked in by npipsl, 11 years ago
File size: 27.1 KB
Line 
1/*
2 Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4
5  The MySQL Connector/J is licensed under the terms of the GPLv2
6  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
7  There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
8  this software, see the FLOSS License Exception
9  <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
10
11  This program is free software; you can redistribute it and/or modify it under the terms
12  of the GNU General Public License as published by the Free Software Foundation; version 2
13  of the License.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
16  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  See the GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License along with this
20  program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
21  Floor, Boston, MA 02110-1301  USA
22
23 */
24
25package com.mysql.jdbc;
26
27import java.io.ByteArrayInputStream;
28import java.io.ByteArrayOutputStream;
29import java.io.InputStream;
30import java.io.IOException;
31import java.io.OutputStream;
32import java.io.Reader;
33import java.io.StringReader;
34import java.io.StringWriter;
35import java.io.UnsupportedEncodingException;
36import java.io.Writer;
37import java.sql.SQLException;
38import java.sql.SQLFeatureNotSupportedException;
39import java.sql.SQLXML;
40
41import javax.xml.transform.Transformer;
42import javax.xml.transform.TransformerFactory;
43import javax.xml.parsers.DocumentBuilder;
44import javax.xml.parsers.DocumentBuilderFactory;
45import javax.xml.parsers.FactoryConfigurationError;
46import javax.xml.parsers.ParserConfigurationException;
47import javax.xml.parsers.SAXParser;
48import javax.xml.parsers.SAXParserFactory;
49import javax.xml.stream.XMLInputFactory;
50import javax.xml.stream.XMLOutputFactory;
51import javax.xml.stream.XMLStreamException;
52import javax.xml.stream.XMLStreamReader;
53import javax.xml.transform.Result;
54import javax.xml.transform.Source;
55import javax.xml.transform.dom.DOMResult;
56import javax.xml.transform.dom.DOMSource;
57import javax.xml.transform.sax.SAXResult;
58import javax.xml.transform.sax.SAXSource;
59import javax.xml.transform.stax.StAXResult;
60import javax.xml.transform.stax.StAXSource;
61import javax.xml.transform.stream.StreamResult;
62import javax.xml.transform.stream.StreamSource;
63
64import org.w3c.dom.DOMException;
65import org.w3c.dom.Document;
66import org.xml.sax.Attributes;
67import org.xml.sax.InputSource;
68import org.xml.sax.helpers.DefaultHandler;
69import org.xml.sax.SAXException;
70
71
72
73public class JDBC4MysqlSQLXML implements SQLXML {
74
75        private XMLInputFactory inputFactory;
76
77        private XMLOutputFactory outputFactory;
78
79        private String stringRep;
80
81        private ResultSetInternalMethods owningResultSet;
82
83        private int columnIndexOfXml;
84
85        private boolean fromResultSet;
86
87        private boolean isClosed = false;
88
89        private boolean workingWithResult;
90
91        private DOMResult asDOMResult;
92
93        private SAXResult asSAXResult;
94
95        private SimpleSaxToReader saxToReaderConverter;
96
97        private StringWriter asStringWriter;
98
99        private ByteArrayOutputStream asByteArrayOutputStream;
100
101        private ExceptionInterceptor exceptionInterceptor;
102       
103        protected JDBC4MysqlSQLXML(ResultSetInternalMethods owner, int index, ExceptionInterceptor exceptionInterceptor) {
104                this.owningResultSet = owner;
105                this.columnIndexOfXml = index;
106                this.fromResultSet = true;
107                this.exceptionInterceptor = exceptionInterceptor;
108        }
109
110        protected JDBC4MysqlSQLXML(ExceptionInterceptor exceptionInterceptor) {
111                this.fromResultSet = false;
112                this.exceptionInterceptor = exceptionInterceptor;
113        }
114
115        public synchronized void free() throws SQLException {
116                this.stringRep = null;
117                this.asDOMResult = null;
118                this.asSAXResult = null;
119                this.inputFactory = null;
120                this.outputFactory = null;
121                this.owningResultSet = null;
122                this.workingWithResult = false;
123                this.isClosed = true;
124
125        }
126
127        public synchronized String getString() throws SQLException {
128                checkClosed();
129                checkWorkingWithResult();
130
131                if (this.fromResultSet) {
132                        return this.owningResultSet.getString(this.columnIndexOfXml);
133                }
134
135                return this.stringRep;
136        }
137
138        private synchronized void checkClosed() throws SQLException {
139                if (this.isClosed) {
140                        throw SQLError
141                                        .createSQLException("SQLXMLInstance has been free()d", this.exceptionInterceptor);
142                }
143        }
144
145        private synchronized void checkWorkingWithResult() throws SQLException {
146                if (this.workingWithResult) {
147                        throw SQLError
148                                        .createSQLException(
149                                                        "Can't perform requested operation after getResult() has been called to write XML data",
150                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
151                }
152        }
153
154        /**
155         * Sets the XML value designated by this SQLXML instance to the given String
156         * representation. The format of this String is defined by
157         * org.xml.sax.InputSource, where the characters in the stream represent the
158         * unicode code points for XML according to section 2 and appendix B of the
159         * XML 1.0 specification. Although an encoding declaration other than
160         * unicode may be present, the encoding of the String is unicode. The
161         * behavior of this method is the same as ResultSet.updateString() when the
162         * designated column of the ResultSet has a type java.sql.Types of SQLXML.
163         * <p>
164         * The SQL XML object becomes not writeable when this method is called and
165         * may also become not readable depending on implementation.
166         *
167         * @param value
168         *            the XML value
169         * @throws SQLException
170         *             if there is an error processing the XML value. The getCause()
171         *             method of the exception may provide a more detailed
172         *             exception, for example, if the stream does not contain valid
173         *             characters. An exception is thrown if the state is not
174         *             writable.
175         * @exception SQLFeatureNotSupportedException
176         *                if the JDBC driver does not support this method
177         * @since 1.6
178         */
179
180        public synchronized void setString(String str) throws SQLException {
181                checkClosed();
182                checkWorkingWithResult();
183
184                this.stringRep = str;
185                this.fromResultSet = false;
186        }
187
188        public synchronized boolean isEmpty() throws SQLException {
189                checkClosed();
190                checkWorkingWithResult();
191
192                if (!this.fromResultSet) {
193                        return this.stringRep == null || this.stringRep.length() == 0;
194                }
195
196                return false;
197        }
198
199        public synchronized InputStream getBinaryStream() throws SQLException {
200                checkClosed();
201                checkWorkingWithResult();
202
203                return this.owningResultSet.getBinaryStream(this.columnIndexOfXml);
204        }
205
206        /**
207         * Retrieves the XML value designated by this SQLXML instance as a
208         * java.io.Reader object. The format of this stream is defined by
209         * org.xml.sax.InputSource, where the characters in the stream represent the
210         * unicode code points for XML according to section 2 and appendix B of the
211         * XML 1.0 specification. Although an encoding declaration other than
212         * unicode may be present, the encoding of the stream is unicode. The
213         * behavior of this method is the same as ResultSet.getCharacterStream()
214         * when the designated column of the ResultSet has a type java.sql.Types of
215         * SQLXML.
216         * <p>
217         * The SQL XML object becomes not readable when this method is called and
218         * may also become not writable depending on implementation.
219         *
220         * @return a stream containing the XML data.
221         * @throws SQLException
222         *             if there is an error processing the XML value. The getCause()
223         *             method of the exception may provide a more detailed
224         *             exception, for example, if the stream does not contain valid
225         *             characters. An exception is thrown if the state is not
226         *             readable.
227         * @exception SQLFeatureNotSupportedException
228         *                if the JDBC driver does not support this method
229         * @since 1.6
230         */
231        public synchronized Reader getCharacterStream() throws SQLException {
232                checkClosed();
233                checkWorkingWithResult();
234
235                return this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
236        }
237
238        /**
239         * Returns a Source for reading the XML value designated by this SQLXML
240         * instance. Sources are used as inputs to XML parsers and XSLT
241         * transformers.
242         * <p>
243         * Sources for XML parsers will have namespace processing on by default. The
244         * systemID of the Source is implementation dependent.
245         * <p>
246         * The SQL XML object becomes not readable when this method is called and
247         * may also become not writable depending on implementation.
248         * <p>
249         * Note that SAX is a callback architecture, so a returned SAXSource should
250         * then be set with a content handler that will receive the SAX events from
251         * parsing. The content handler will receive callbacks based on the contents
252         * of the XML.
253         *
254         * <pre>
255         * SAXSource saxSource = sqlxml.getSource(SAXSource.class);
256         * XMLReader xmlReader = saxSource.getXMLReader();
257         * xmlReader.setContentHandler(myHandler);
258         * xmlReader.parse(saxSource.getInputSource());
259         * </pre>
260         *
261         * @param sourceClass
262         *            The class of the source, or null. If the class is null, a
263         *            vendor specifc Source implementation will be returned. The
264         *            following classes are supported at a minimum:
265         *
266         * (MySQL returns a SAXSource if sourceClass == null)
267         *
268         * <pre>
269         *    javax.xml.transform.dom.DOMSource - returns a DOMSource
270         *    javax.xml.transform.sax.SAXSource - returns a SAXSource
271         *    javax.xml.transform.stax.StAXSource - returns a StAXSource
272         *    javax.xml.transform.stream.StreamSource - returns a StreamSource
273         * </pre>
274         *
275         * @return a Source for reading the XML value.
276         * @throws SQLException
277         *             if there is an error processing the XML value or if this
278         *             feature is not supported. The getCause() method of the
279         *             exception may provide a more detailed exception, for example,
280         *             if an XML parser exception occurs. An exception is thrown if
281         *             the state is not readable.
282         * @exception SQLFeatureNotSupportedException
283         *                if the JDBC driver does not support this method
284         * @since 1.6
285         */
286        public synchronized Source getSource(Class clazz) throws SQLException {
287                checkClosed();
288                checkWorkingWithResult();
289
290                // Note that we try and use streams here wherever possible
291                // for the day that the server actually supports streaming
292                // from server -> client (futureproofing)
293
294                if (clazz == null || clazz.equals(SAXSource.class)) {
295
296                        InputSource inputSource = null;
297
298                        if (this.fromResultSet) {
299                                inputSource = new InputSource(this.owningResultSet
300                                                .getCharacterStream(this.columnIndexOfXml));
301                        } else {
302                                inputSource = new InputSource(new StringReader(this.stringRep));
303                        }
304
305                        return new SAXSource(inputSource);
306                } else if (clazz.equals(DOMSource.class)) {
307                        try {
308                                DocumentBuilderFactory builderFactory = DocumentBuilderFactory
309                                                .newInstance();
310                                builderFactory.setNamespaceAware(true);
311                                DocumentBuilder builder = builderFactory.newDocumentBuilder();
312
313                                InputSource inputSource = null;
314
315                                if (this.fromResultSet) {
316                                        inputSource = new InputSource(this.owningResultSet
317                                                        .getCharacterStream(this.columnIndexOfXml));
318                                } else {
319                                        inputSource = new InputSource(new StringReader(
320                                                        this.stringRep));
321                                }
322
323                                return new DOMSource(builder.parse(inputSource));
324                        } catch (Throwable t) {
325                                SQLException sqlEx = SQLError.createSQLException(t
326                                                .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
327                                sqlEx.initCause(t);
328                               
329                                throw sqlEx;
330                        }
331
332                } else if (clazz.equals(StreamSource.class)) {
333                        Reader reader = null;
334
335                        if (this.fromResultSet) {
336                                reader = this.owningResultSet
337                                                .getCharacterStream(this.columnIndexOfXml);
338                        } else {
339                                reader = new StringReader(this.stringRep);
340                        }
341
342                        return new StreamSource(reader);
343                } else if (clazz.equals(StAXSource.class)) {
344                        try {
345                                Reader reader = null;
346
347                                if (this.fromResultSet) {
348                                        reader = this.owningResultSet
349                                                        .getCharacterStream(this.columnIndexOfXml);
350                                } else {
351                                        reader = new StringReader(this.stringRep);
352                                }
353
354                                return new StAXSource(this.inputFactory
355                                                .createXMLStreamReader(reader));
356                        } catch (XMLStreamException ex) {
357                                SQLException sqlEx = SQLError.createSQLException(ex
358                                                .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
359                                sqlEx.initCause(ex);
360                               
361                                throw sqlEx;
362                        }
363                } else {
364                        throw SQLError.createSQLException("XML Source of type \""
365                                        + clazz.toString() + "\" Not supported.",
366                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
367                }
368        }
369
370        /**
371         * Retrieves a stream that can be used to write the XML value that this
372         * SQLXML instance represents. The stream begins at position 0. The bytes of
373         * the stream are interpreted according to appendix F of the XML 1.0
374         * specification The behavior of this method is the same as
375         * ResultSet.updateBinaryStream() when the designated column of the
376         * ResultSet has a type java.sql.Types of SQLXML.
377         * <p>
378         * The SQL XML object becomes not writeable when this method is called and
379         * may also become not readable depending on implementation.
380         *
381         * @return a stream to which data can be written.
382         * @throws SQLException
383         *             if there is an error processing the XML value. An exception
384         *             is thrown if the state is not writable.
385         * @exception SQLFeatureNotSupportedException
386         *                if the JDBC driver does not support this method
387         * @since 1.6
388         */
389        public synchronized OutputStream setBinaryStream() throws SQLException {
390                checkClosed();
391                checkWorkingWithResult();
392
393                this.workingWithResult = true;
394
395                return setBinaryStreamInternal();
396        }
397
398        private synchronized OutputStream setBinaryStreamInternal()
399                        throws SQLException {
400                this.asByteArrayOutputStream = new ByteArrayOutputStream();
401
402                return this.asByteArrayOutputStream;
403        }
404
405        /**
406         * Retrieves a stream to be used to write the XML value that this SQLXML
407         * instance represents. The format of this stream is defined by
408         * org.xml.sax.InputSource, where the characters in the stream represent the
409         * unicode code points for XML according to section 2 and appendix B of the
410         * XML 1.0 specification. Although an encoding declaration other than
411         * unicode may be present, the encoding of the stream is unicode. The
412         * behavior of this method is the same as ResultSet.updateCharacterStream()
413         * when the designated column of the ResultSet has a type java.sql.Types of
414         * SQLXML.
415         * <p>
416         * The SQL XML object becomes not writeable when this method is called and
417         * may also become not readable depending on implementation.
418         *
419         * @return a stream to which data can be written.
420         * @throws SQLException
421         *             if there is an error processing the XML value. The getCause()
422         *             method of the exception may provide a more detailed
423         *             exception, for example, if the stream does not contain valid
424         *             characters. An exception is thrown if the state is not
425         *             writable.
426         * @exception SQLFeatureNotSupportedException
427         *                if the JDBC driver does not support this method
428         * @since 1.6
429         */
430        public synchronized Writer setCharacterStream() throws SQLException {
431                checkClosed();
432                checkWorkingWithResult();
433
434                this.workingWithResult = true;
435
436                return setCharacterStreamInternal();
437        }
438
439        private synchronized Writer setCharacterStreamInternal()
440                        throws SQLException {
441                this.asStringWriter = new StringWriter();
442
443                return this.asStringWriter;
444        }
445
446        /**
447         * Returns a Result for setting the XML value designated by this SQLXML
448         * instance.
449         * <p>
450         * The systemID of the Result is implementation dependent.
451         * <p>
452         * The SQL XML object becomes not writeable when this method is called and
453         * may also become not readable depending on implementation.
454         * <p>
455         * Note that SAX is a callback architecture and the returned SAXResult has a
456         * content handler assigned that will receive the SAX events based on the
457         * contents of the XML. Call the content handler with the contents of the
458         * XML document to assign the values.
459         *
460         * <pre>
461         * SAXResult saxResult = sqlxml.setResult(SAXResult.class);
462         * ContentHandler contentHandler = saxResult.getXMLReader().getContentHandler();
463         * contentHandler.startDocument();
464         * // set the XML elements and attributes into the result
465         * contentHandler.endDocument();
466         * </pre>
467         *
468         * @param resultClass
469         *            The class of the result, or null. If resultClass is null, a
470         *            vendor specific Result implementation will be returned. The
471         *            following classes are supported at a minimum:
472         *
473         * <pre>
474         *    javax.xml.transform.dom.DOMResult - returns a DOMResult
475         *    javax.xml.transform.sax.SAXResult - returns a SAXResult
476         *    javax.xml.transform.stax.StAXResult - returns a StAXResult
477         *    javax.xml.transform.stream.StreamResult - returns a StreamResult
478         * </pre>
479         *
480         * @return Returns a Result for setting the XML value.
481         * @throws SQLException
482         *             if there is an error processing the XML value or if this
483         *             feature is not supported. The getCause() method of the
484         *             exception may provide a more detailed exception, for example,
485         *             if an XML parser exception occurs. An exception is thrown if
486         *             the state is not writable.
487         * @exception SQLFeatureNotSupportedException
488         *                if the JDBC driver does not support this method
489         * @since 1.6
490         */
491        public synchronized Result setResult(Class clazz) throws SQLException {
492                checkClosed();
493                checkWorkingWithResult();
494
495                this.workingWithResult = true;
496                this.asDOMResult = null;
497                this.asSAXResult = null;
498                this.saxToReaderConverter = null;
499                this.stringRep = null;
500                this.asStringWriter = null;
501                this.asByteArrayOutputStream = null;
502
503                if (clazz == null || clazz.equals(SAXResult.class)) {
504                        this.saxToReaderConverter = new SimpleSaxToReader();
505
506                        this.asSAXResult = new SAXResult(this.saxToReaderConverter);
507
508                        return this.asSAXResult;
509                } else if (clazz.equals(DOMResult.class)) {
510
511                        this.asDOMResult = new DOMResult();
512                        return this.asDOMResult;
513
514                } else if (clazz.equals(StreamResult.class)) {
515                        return new StreamResult(setCharacterStreamInternal());
516                } else if (clazz.equals(StAXResult.class)) {
517                        try {
518                                if (this.outputFactory == null) {
519                                        this.outputFactory = XMLOutputFactory.newInstance();
520                                }
521
522                                return new StAXResult(this.outputFactory
523                                                .createXMLEventWriter(setCharacterStreamInternal()));
524                        } catch (XMLStreamException ex) {
525                                SQLException sqlEx = SQLError.createSQLException(ex
526                                                .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
527                                sqlEx.initCause(ex);
528                               
529                                throw sqlEx;
530                        }
531                } else {
532                        throw SQLError.createSQLException("XML Result of type \""
533                                        + clazz.toString() + "\" Not supported.",
534                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
535                }
536        }
537
538        private Reader binaryInputStreamStreamToReader(ByteArrayOutputStream out) {
539
540                try {
541                        // There's got to be an easier way to do this, but
542                        // I don't feel like coding up Appendix F of the XML Spec
543                        // myself, when there's a reusable way to do it, and we
544                        // can warn folks away from BINARY xml streams that have
545                        // to be parsed to determine the character encoding :P
546
547                        String encoding = "UTF-8";
548
549                        try {
550                                ByteArrayInputStream bIn = new ByteArrayInputStream(out
551                                                .toByteArray());
552                                XMLStreamReader reader = this.inputFactory
553                                                .createXMLStreamReader(bIn);
554
555                                int eventType = 0;
556
557                                while ((eventType = reader.next()) != XMLStreamReader.END_DOCUMENT) {
558                                        if (eventType == XMLStreamReader.START_DOCUMENT) {
559                                                String possibleEncoding = reader.getEncoding();
560
561                                                if (possibleEncoding != null) {
562                                                        encoding = possibleEncoding;
563                                                }
564
565                                                break;
566                                        }
567                                }
568                        } catch (Throwable t) {
569                                // ignore, dealt with later when the string can't be parsed
570                                // into valid XML
571                        }
572
573                        return new StringReader(new String(out.toByteArray(), encoding));
574                } catch (UnsupportedEncodingException badEnc) {
575                        throw new RuntimeException(badEnc);
576                }
577        }
578
579        protected String readerToString(Reader reader) throws SQLException {
580                StringBuffer buf = new StringBuffer();
581               
582                int charsRead = 0;
583               
584                char[] charBuf = new char[512];
585               
586                try {
587                        while ((charsRead = reader.read(charBuf)) != -1) {
588                                buf.append(charBuf, 0, charsRead);
589                        }
590                } catch (IOException ioEx) {
591                        SQLException sqlEx = SQLError.createSQLException(ioEx
592                                        .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
593                        sqlEx.initCause(ioEx);
594                       
595                        throw sqlEx;
596                }
597               
598                return buf.toString();
599        }
600       
601        protected synchronized Reader serializeAsCharacterStream()
602                        throws SQLException {
603                checkClosed();
604                if (this.workingWithResult) {
605                        // figure out what kind of result
606                        if (this.stringRep != null) {
607                                return new StringReader(this.stringRep);
608                        }
609
610                        if (this.asDOMResult != null) {
611                                return new StringReader(domSourceToString());
612                        }
613
614                        if (this.asStringWriter != null) { // stax result
615                                return new StringReader(this.asStringWriter.toString());
616                        }
617                       
618                        if (this.asSAXResult != null) {
619                                return this.saxToReaderConverter.toReader();
620                        }
621
622                        if (this.asByteArrayOutputStream != null) {
623                                return binaryInputStreamStreamToReader(this.asByteArrayOutputStream);
624                        }
625                }
626
627                return this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
628        }
629
630        protected String domSourceToString() throws SQLException {
631                try {
632                        DOMSource source = new DOMSource(this.asDOMResult.getNode());
633                        Transformer identity = TransformerFactory.newInstance()
634                                        .newTransformer();
635                        StringWriter stringOut = new StringWriter();
636                        Result result = new StreamResult(stringOut);
637                        identity.transform(source, result);
638       
639                        return stringOut.toString();
640                } catch (Throwable t) {
641                        SQLException sqlEx = SQLError.createSQLException(t
642                                        .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor);
643                        sqlEx.initCause(t);
644                       
645                        throw sqlEx;
646                }
647        }
648       
649        protected synchronized String serializeAsString() throws SQLException {
650                checkClosed();
651                if (this.workingWithResult) {
652                        // figure out what kind of result
653                        if (this.stringRep != null) {
654                                return this.stringRep;
655                        }
656
657                        if (this.asDOMResult != null) {
658                                return domSourceToString();
659                        }
660                       
661                        if (this.asStringWriter != null) { // stax result
662                                return this.asStringWriter.toString();
663                        }
664                       
665                        if (this.asSAXResult != null) {
666                                return readerToString(this.saxToReaderConverter.toReader());
667                        }
668
669                        if (this.asByteArrayOutputStream != null) {
670                                return readerToString(
671                                                binaryInputStreamStreamToReader(this.asByteArrayOutputStream));
672                        }
673                }
674
675                return this.owningResultSet.getString(this.columnIndexOfXml);
676        }
677
678        /*
679         * The SimpleSaxToReader class is an adaptation of the SAX "Writer"
680         * example from the Apache XercesJ-2 Project. The license for this
681         * code is as follows:
682         *
683         * Licensed to the Apache Software Foundation (ASF) under one or more
684         * contributor license agreements.  See the NOTICE file distributed with
685         * this work for additional information regarding copyright ownership.
686         * The ASF licenses this file to You under the Apache License, Version 2.0
687         * (the "License"); you may not use this file except in compliance with
688         * the License.  You may obtain a copy of the License at
689         *
690         *      http://www.apache.org/licenses/LICENSE-2.0
691         *
692         * Unless required by applicable law or agreed to in writing, software
693         * distributed under the License is distributed on an "AS IS" BASIS,
694         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
695         * See the License for the specific language governing permissions and
696         * limitations under the License.
697         */
698
699        class SimpleSaxToReader extends DefaultHandler {
700                StringBuffer buf = new StringBuffer();
701
702                public void startDocument() throws SAXException {
703                        buf.append("<?xml version='1.0' encoding='UTF-8'?>");
704                }
705
706                public void endDocument() throws SAXException {
707                        // Do we need to override this?
708                }
709
710                public void startElement(String namespaceURI, String sName,
711                                String qName, Attributes attrs) throws SAXException {
712
713                        this.buf.append("<");
714                        this.buf.append(qName);
715
716                        if (attrs != null) {
717                                for (int i = 0; i < attrs.getLength(); i++) {
718                                        this.buf.append(" ");
719                                        this.buf.append(attrs.getQName(i)).append("=\"");
720                                        escapeCharsForXml(attrs.getValue(i), true);
721                                        this.buf.append("\"");
722                                }
723                        }
724
725                        this.buf.append(">");
726                }
727
728                public void characters(char buf[], int offset, int len)
729                                throws SAXException {
730                        if (!this.inCDATA) {
731                                escapeCharsForXml(buf, offset, len, false);
732                        } else {
733                                this.buf.append(buf, offset, len);
734                        }
735                }
736
737                public void ignorableWhitespace(char ch[], int start, int length)
738                                throws SAXException {
739                        characters(ch, start, length);
740                }
741
742                private boolean inCDATA = false;
743
744                public void startCDATA() throws SAXException {
745                        this.buf.append("<![CDATA[");
746                        this.inCDATA = true;
747                }
748
749                public void endCDATA() throws SAXException {
750                        this.inCDATA = false;
751                        this.buf.append("]]>");
752                }
753
754                public void comment(char ch[], int start, int length)
755                                throws SAXException {
756                        // if (!fCanonical && fElementDepth > 0) {
757                        this.buf.append("<!--");
758                        for (int i = 0; i < length; ++i) {
759                                this.buf.append(ch[start + i]);
760                        }
761                        this.buf.append("-->");
762                        // }
763                }
764
765                Reader toReader() {
766                        return new StringReader(this.buf.toString());
767                }
768
769                private void escapeCharsForXml(String str, boolean isAttributeData) {
770                        if (str == null) {
771                                return;
772                        }
773
774                        int strLen = str.length();
775
776                        for (int i = 0; i < strLen; i++) {
777                                escapeCharsForXml(str.charAt(i), isAttributeData);
778                        }
779                }
780
781                private void escapeCharsForXml(char[] buf, int offset, int len,
782                                boolean isAttributeData) {
783
784                        if (buf == null) {
785                                return;
786                        }
787
788                        for (int i = 0; i < len; i++) {
789                                escapeCharsForXml(buf[offset + i], isAttributeData);
790                        }
791                }
792
793                private void escapeCharsForXml(char c, boolean isAttributeData) {
794                        switch (c) {
795                        case '<': 
796                                this.buf.append("&lt;");
797                                break;
798                       
799                        case '>': 
800                                this.buf.append("&gt;");
801                                break;
802                       
803                        case '&':
804                                this.buf.append("&amp;");
805                                break;
806                       
807                        case '"': 
808
809                                if (!isAttributeData) {
810                                        this.buf.append("\"");
811                                }
812                                else {
813                                        this.buf.append("&quot;");
814                                }
815
816                                break;
817               
818                        case '\r': 
819                                this.buf.append("&#xD;");
820                                break;
821                       
822
823                        default: 
824
825                                if (((c >= 0x01 && c <= 0x1F && c != 0x09 && c != 0x0A) 
826                                                || (c >= 0x7F && c <= 0x9F) || c == 0x2028)
827                                                || isAttributeData && (c == 0x09 || c == 0x0A)) {
828                                        this.buf.append("&#x");
829                                        this.buf.append(Integer.toHexString(c).toUpperCase());
830                                        this.buf.append(";");
831                                }
832                                else {
833                                        this.buf.append(c);
834                                }                       
835                        }
836                }
837        }
838}
Note: See TracBrowser for help on using the repository browser.