PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/EQEmuJSM/mysql-connector-java-5.1.13/src/com/mysql/jdbc/JDBC4MysqlSQLXML.java

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