db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ян Программист <webautoma...@gmail.com>
Subject SQLXML Research report
Date Sat, 03 Apr 2010 08:36:31 GMT
While figuring out necessary information about SQLXML, I found that it is a
JDBC 4 issue, according to SQL 2003(?) standard specification. I found
following databases containing SQLXML implementation:



SQL Server 2008

HyperSQL

PostgreSQL



Other databases have XML support in SQL syntax, for example H2 database, but
I haven't found anything about SQLXML in their JDBC API



So I digged a bit in HyperSQL API Javadoc, and here is what I've found in
org.hsqldb.jdbc.JDBCSQLXML.html:





“*HSQLDB-Specific Information:*



Starting with HSQLDB 1.9.0, a rudimentary client-side SQLXML interface
implementation (this class) is supported for local use when the product is
built and run under JDK 1.6+ and the SQLXML instance is constructed as the
result of calling JDBCConnection.createSQLXML().



SQLXML instances retrieved in such a fashion are initially write-only, with
the lifecycle of read and write availability constrained in accordance with
the documentation of the interface methods.



When build and run under JDK 1.6+, it is also possible to retrieve read-only
SQLXML instances from JDBCResultSet.getSQLXML(...), given that the
underlying data can be converted to an XML Document Object Model (DOM).



However, at the time of this writing (2007-06-12) it is not yet possible to
store SQLXML objects directly into an HSQLDB database or to use them
directly for HSQLDB statement parameterization purposes. This is because the
SQLXML data type is not yet natively supported by the HSQLDB engine.
Instead, a JDBCSQLXML instance must first be read as a string, binary input
stream, character input stream and so on, which can then be used for such
purposes.



Here is the current read/write availability lifecycle for JDBCSQLXML:



Origin

Initially

After 1st Write

After 1st Read

After 1st Free

*org.hsqldb.jdbc.JDBC**Connection**.createSQLXML()*

Write-only

Read-only

Not readable or writable

Not readable or writable

*org.hsqldb.jdbc.JDBC**ResultSet**.getSQLXML(...)*

Read-only

N/A

Not readable or writable

Not readable or writable

.”



My conclusions:

   1. Hence a difference in class purpose, between JDBCConnection &
   JDBCResultSet

◦                  JDBCConnection is obviously dictates data exange mode.
Looks similar to global XML mode in MySQL, stating from version 5

◦                  JDBCResultSet implies that some general SQL request is
performed already. An that is *exactly what I was seeking* for:



So I continued my lookup and found this in HyperSQL source code:



JDBCResultSet.java:

  /**

     * Retrieves the value of the designated column in  the current row of

     *  this <code>ResultSet</code> as a

     * <code>java.sql.SQLXML</code> object in the Java programming language.

     *

     * @param columnIndex the first column is 1, the second is 2, ...

     * @return a <code>SQLXML</code> object that maps an <code>SQL
XML</code> value

     * @throws SQLException if a database access error occurs

     * or this method is called on a closed result set

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6, HSQLDB 1.9.0

     */

//#ifdef JAVA6

    *public SQLXML getSQLXML(int columnIndex) throws SQLException* {



        checkColumn(columnIndex);



        SQLXML sqlxml;

        int    type = resultMetaData.columnTypes[columnIndex - 1].typeCode;



        switch (type) {



            case *Types.**SQL_XML* : {

                Object object = getObject(columnIndex);



                if (object == null) {

                    sqlxml = null;

                } else if (object instanceof SQLXML) {

                    sqlxml = (SQLXML) object;

                } else {

                    throw Util.notSupported();

                }



                break;

            }

            case Types.SQL_CLOB : {

                Clob clob = getClob(columnIndex);



                if (clob == null) {

                    sqlxml = null;

                } else {

                    sqlxml = new JDBCSQLXML(clob.getCharacterStream());

                }



                break;

            }

            case Types.SQL_CHAR :

            case Types.SQL_VARCHAR :

            case Types.VARCHAR_IGNORECASE : {

                java.io.Reader reader = getCharacterStream(columnIndex);



                if (reader == null) {

                    sqlxml = null;

                } else {

                    sqlxml = new JDBCSQLXML(reader);

                }



                break;

            }

            case Types.SQL_NCHAR :

            case Types.SQL_NVARCHAR : {

                java.io.Reader nreader = getNCharacterStream(columnIndex);



                if (nreader == null) {

                    sqlxml = null;

                } else {

                    sqlxml = new JDBCSQLXML(nreader);

                }



                break;

            }

            case Types.SQL_BLOB : {

                Blob blob = getBlob(columnIndex);



                if (blob == null) {

                    sqlxml = null;

                } else {

                    sqlxml = new JDBCSQLXML(blob.getBinaryStream());

                }



                break;

            }

            case Types.SQL_BINARY :

            case Types.SQL_VARBINARY : {

                java.io.InputStream inputStream =
getBinaryStream(columnIndex);



                if (inputStream == null) {

                    sqlxml = null;

                } else {

                    sqlxml = new JDBCSQLXML(inputStream);

                }



                break;

            }

            case Types.OTHER :

            case Types.JAVA_OBJECT : {

                Object data = getObject(columnIndex);



                if (data == null) {

                    sqlxml = null;

                } else if (data instanceof SQLXML) {

                    sqlxml = (SQLXML) data;

                } else if (data instanceof String) {

                    sqlxml = new JDBCSQLXML((String) data);

                } else if (data instanceof byte[]) {

                    sqlxml = new JDBCSQLXML((byte[]) data);

                } else if (data instanceof Blob) {

                    Blob blob = (Blob) data;



                    sqlxml = new JDBCSQLXML(blob.getBinaryStream());

                } else if (data instanceof Clob) {

                    Clob clob = (Clob) data;



                    sqlxml = new JDBCSQLXML(clob.getCharacterStream());

                } else {

                    throw Util.notSupported();

                }



                break;

            }

            default : {

                throw Util.notSupported();

            }

        }



        return sqlxml;

    }



//#endif JAVA6



    /**

     * Retrieves the value of the designated column in  the current row of

     *  this <code>ResultSet</code> as a

     * <code>java.sql.SQLXML</code> object in the Java programming language.

     * @param columnLabel the label for the column specified with the SQL AS

     * clause.  If the SQL AS clause was not specified, then the label is
the

     * name of the column

     * @return a <code>SQLXML</code> object that maps an <code>SQL
XML</code> value

     * @throws SQLException if a database access error occurs

     * or this method is called on a closed result set

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6, HSQLDB 1.9.0

     */

//#ifdef JAVA6

    *public SQLXML getSQLXML(String columnLabel) throws SQLException* {

        return getSQLXML(findColumn(columnLabel));

    }



//#endif JAVA6



    /**

     * Updates the designated column with a <code>java.sql.SQLXML</code>
value.

     * The updater

     * methods are used to update column values in the current row or the
insert

     * row. The updater methods do not update the underlying database;
instead

     * the <code>updateRow</code> or <code>insertRow</code> methods are
called

     * to update the database.

     * <p>

     *

     * @param columnIndex the first column is 1, the second 2, ...

     * @param xmlObject the value for the column to be updated

     * @throws SQLException if a database access error occurs, this method

     *  is called on a closed result set,

     * the <code>java.xml.transform.Result</code>,

     *  <code>Writer</code> or <code>OutputStream</code> has not been closed

     * for the <code>SQLXML</code> object,

     *  if there is an error processing the XML value or

     * the result set concurrency is <code>CONCUR_READ_ONLY</code>.  The
<code>getCause</code> method

     *  of the exception may provide a more detailed exception, for example,
if the

     *  stream does not contain valid XML.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6, HSQLDB 1.9.0

     */

//#ifdef JAVA6

    *public void updateSQLXML(int columnIndex,*

*                             SQLXML xmlObject) throws SQLException* {

        startUpdate(columnIndex);

        preparedStatement.setSQLXML(columnIndex, xmlObject);

    }



//#endif JAVA6



    /**

     * Updates the designated column with a <code>java.sql.SQLXML</code>
value.

     * The updater

     * methods are used to update column values in the current row or the
insert

     * row. The updater methods do not update the underlying database;
instead

     * the <code>updateRow</code> or <code>insertRow</code> methods are
called

     * to update the database.

     * <p>

     *

     * @param columnLabel the label for the column specified with the SQL AS

     * clause.  If the SQL AS clause was not specified, then the label is
the

     * name of the column

     * @param xmlObject the column value

     * @throws SQLException if a database access error occurs, this method

     *  is called on a closed result set,

     * the <code>java.xml.transform.Result</code>,

     *  <code>Writer</code> or <code>OutputStream</code> has not been closed

     * for the <code>SQLXML</code> object,

     *  if there is an error processing the XML value or

     * the result set concurrency is <code>CONCUR_READ_ONLY</code>.  The
<code>getCause</code> method

     *  of the exception may provide a more detailed exception, for example,
if the

     *  stream does not contain valid XML.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6, HSQLDB 1.9.0

     */

//#ifdef JAVA6

    *public void updateSQLXML(String columnLabel,*

*                             SQLXML xmlObject) throws SQLException* {

        updateSQLXML(findColumn(columnLabel), xmlObject);

    }



//#endif JAVA6





Hence  Types.SQL_XML. It looks like some kind of dedicated column type in
HyperSQL database. So I explored it also:


    While not been found in org.hsqldb.types.*, it was found in
org.hsqldb.Types.java:


package org.hsqldb;

import org.hsqldb.lib.HashSet;
import org.hsqldb.lib.IntValueHashMap;
import org.hsqldb.persist.HsqlDatabaseProperties;

// boucherb@users 20051207 - patch 1.8.x initial JDBC 4.0 support work

/**
 * Defines the constants that are used to identify SQL types for HSQLDB JDBC
 * inteface type reporting. The actual type constant values are equivalent
 * to those defined in the latest java.sql.Types, where available,
 * or those defined by ansi/iso SQL 2003 otherwise. A type sub-identifer
 * has been added to differentiate HSQLDB-specific type specializations.
 *
 * @author  boucherb@users
 * @version 1.8.x
 * @since 1.7.2
 */
public class Types {

    /**
     * Names of types returned by JDBC methods and accepted as
     * library and user function arguments
     */
    public static final String DecimalClassName   = "java.math.BigDecimal";
    public static final String DateClassName      = "java.sql.Date";
    public static final String TimeClassName      = "java.sql.Time";
    public static final String TimestampClassName = "java.sql.Timestamp";
    public static final String BlobClassName      = "java.sql.Blob";
    public static final String ClobClassName      = "java.sql.Clob";
    /*
     SQL specifies predefined data types named by the following <key word>s:
     CHARACTER, CHARACTER VARYING, CHARACTER LARGE OBJECT, BINARY LARGE
OBJECT,
     NUMERIC, DECIMAL, SMALLINT, INTEGER, BIGINT, FLOAT, REAL, DOUBLE
PRECISION,
     BOOLEAN, DATE, TIME, TIMESTAMP, and INTERVAL. Also BINARY and VARBINARY
     in SQL post-2003
     SQL 2003 adds DATALINK in Part 9: Management of External Data (SQL/MED)
     *and adds XML in Part 14: XML-Related Specifications (SQL/XML)*
     */

    // CLI type list from Table 37
    public static final int SQL_CHAR              = 1;
    public static final int SQL_NUMERIC           = 2;
    public static final int SQL_DECIMAL           = 3;
    public static final int SQL_INTEGER           = 4;
    public static final int SQL_SMALLINT          = 5;
    public static final int SQL_FLOAT             = 6;
    public static final int SQL_REAL              = 7;
    public static final int SQL_DOUBLE            = 8;
    public static final int SQL_VARCHAR           = 12;
    public static final int SQL_BOOLEAN           = 16;
    public static final int SQL_USER_DEFINED_TYPE = 17;
    public static final int SQL_ROW               = 19;
    public static final int SQL_REF               = 20;
    public static final int SQL_BIGINT            = 25;             //
different in JDBC
    public static final int SQL_BLOB              = 30;             //
different in JDBC
    public static final int SQL_CLOB              = 40;             //
different in JDBC
    public static final int SQL_ARRAY             = 50;             //
different in JDBC - not predefined
    public static final int SQL_MULTISET = 55;                      //
    public static final int SQL_BINARY   = 60;                      //
different in JDBC -in SQL post-2003
    public static final int SQL_VARBINARY = 61;                     //
different in JDBC - in SQL post-2003
    public static final int SQL_DATE                      = 91;
    public static final int SQL_TIME                      = 92;
    public static final int SQL_TIMESTAMP                 = 93;     //
    public static final int SQL_TIME_WITH_TIME_ZONE       = 94;
    public static final int SQL_TIMESTAMP_WITH_TIME_ZONE  = 95;     //
    public static final int SQL_INTERVAL_YEAR             = 101;    //
    public static final int SQL_INTERVAL_MONTH            = 102;
    public static final int SQL_INTERVAL_DAY              = 103;
    public static final int SQL_INTERVAL_HOUR             = 104;
    public static final int SQL_INTERVAL_MINUTE           = 105;
    public static final int SQL_INTERVAL_SECOND           = 106;
    public static final int SQL_INTERVAL_YEAR_TO_MONTH    = 107;
    public static final int SQL_INTERVAL_DAY_TO_HOUR      = 108;
    public static final int SQL_INTERVAL_DAY_TO_MINUTE    = 109;
    public static final int SQL_INTERVAL_DAY_TO_SECOND    = 110;
    public static final int SQL_INTERVAL_HOUR_TO_MINUTE   = 111;
    public static final int SQL_INTERVAL_HOUR_TO_SECOND   = 112;
    public static final int SQL_INTERVAL_MINUTE_TO_SECOND = 113;

    // used where local defines are used in the same range as SQL type
numbers
    public static final int SQL_TYPE_NUMBER_LIMIT = 256;

    // These values are not in table 37 of the SQL CLI 2003 FCD, but some
    // are found in tables 6-9 and some are found in Annex A1:
    // c Header File SQLCLI.H and/or addendums in other documents,
    // such as:
    // SQL 2003 Part 9: Management of External Data (SQL/MED) : DATALINK
    // SQL 2003 Part 14: XML-Related Specifications (SQL/XML) : XML
    public static final int SQL_BIT         = 14;                   // is in
SQL99 but removed from 2003
    public static final int SQL_BIT_VARYING = 15;                   // is in
SQL99 but removed from 2003
    public static final int SQL_DATALINK         = 70;
    public static final int SQL_UDT              = 17;
    public static final int SQL_UDT_LOCATOR      = 18;
    public static final int SQL_BLOB_LOCATOR     = 31;
    public static final int SQL_CLOB_LOCATOR     = 41;
    public static final int SQL_ARRAY_LOCATOR    = 51;
    public static final int SQL_MULTISET_LOCATOR = 56;
    public static final int SQL_ALL_TYPES        = 0;
    public static final int SQL_DATETIME         = 9;               //
collective name
    public static final int SQL_INTERVAL         = 10;              //
collective name
    public static final int SQL_XML              = 137;

    // These values are taken from various SQL CLI header files
    public static final int SQL_NCHAR         = (-8);
    public static final int SQL_WCHAR         = (-8);
    public static final int SQL_WVARCHAR      = (-9);
    public static final int SQL_NVARCHAR      = (-9);
    public static final int SQL_WLONGVARCHAR  = (-10);
    public static final int SQL_NTEXT         = (-10);
    public static final int SQL_LONGVARBINARY = (-4);
    public static final int SQL_IMAGE         = (-4);
    public static final int SQL_GUID          = (-11);
    public static final int SQL_VARIANT       = (-150);

    // SQL_UDT subcodes
    public static final int SQL_SUB_DISTINCT   = 1;
    public static final int SQL_SUB_STRUCTURED = 2;

    // non-standard type not in JDBC or SQL CLI
    public static final int VARCHAR_IGNORECASE = 100;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
     * <code>ARRAY</code>.
     *
     * @since JDK 1.2
     */
    public static final int ARRAY = 2003;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>BIGINT</code>.
     */
    public static final int BIGINT = -5;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>BINARY</code>.
     */
    public static final int BINARY = -2;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>BIT</code>.
     */
    public static final int BIT = -7;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
     * <code>BLOB</code>.
     *
     * @since JDK 1.2
     */
    public static final int BLOB = 2004;

    /**
     * The constant in the Java programming language, somtimes referred to
     * as a type code, that identifies the generic SQL type
     * <code>BOOLEAN</code>.
     *
     * @since JDK 1.4
     */
    public static final int BOOLEAN = SQL_BOOLEAN;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>CHAR</code>.
     */
    public static final int CHAR = SQL_CHAR;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
     * <code>CLOB</code>
     *
     * @since JDK 1.2
     */
    public static final int CLOB = 2005;

    /**
     * The constant in the Java programming language, somtimes referred to
     * as a type code, that identifies the generic SQL type
<code>DATALINK</code>.
     *
     * @since JDK 1.4
     */
    public static final int DATALINK = 70;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>DATE</code>.
     */
    public static final int DATE = SQL_DATE;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>DECIMAL</code>.
     */
    public static final int DECIMAL = SQL_DECIMAL;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
     * <code>DISTINCT</code>.
     *
     * @since JDK 1.2
     */
    public static final int DISTINCT = 2001;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>DOUBLE</code>.
     */
    public static final int DOUBLE = SQL_DOUBLE;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>FLOAT</code>.
     */
    public static final int FLOAT = SQL_FLOAT;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>INTEGER</code>.
     */
    public static final int INTEGER = SQL_INTEGER;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
     * <code>JAVA_OBJECT</code>.
     *
     * @since JDK 1.2
     */
    public static final int JAVA_OBJECT = 2000;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>LONGVARBINARY</code>.
     */
    public static final int LONGVARBINARY = -4;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>LONGVARCHAR</code>.
     */
    public static final int LONGVARCHAR = -1;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>NULL</code>.
     */
    public static final int NULL = 0;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>NUMERIC</code>.
     */
    public static final int NUMERIC = SQL_NUMERIC;

    /**
     * The constant in the Java programming language that indicates
     * that the SQL type is database-specific and
     * gets mapped to a Java object that can be accessed via
     * the methods <code>getObject</code> and <code>setObject</code>.
     */
    public static final int OTHER = 1111;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>REAL</code>.
     */
    public static final int REAL = SQL_REAL;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
     * <code>REF</code>.
     *
     * @since JDK 1.2
     */
    public static final int REF = 2006;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>SMALLINT</code>.
     */
    public static final int SMALLINT = SQL_SMALLINT;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
     * <code>STRUCT</code>.
     *
     * @since JDK 1.2
     */
    public static final int STRUCT = 2002;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>TIME</code>.
     */
    public static final int TIME = SQL_TIME;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>TIMESTAMP</code>.
     */
    public static final int TIMESTAMP = SQL_TIMESTAMP;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>TINYINT</code>.
     */
    public static final int TINYINT = -6;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>VARBINARY</code>.
     */
    public static final int VARBINARY = -3;

    /**
     * <P>The constant in the Java programming language, sometimes referred
     * to as a type code, that identifies the generic SQL type
     * <code>VARCHAR</code>.
     */
    public static final int VARCHAR = SQL_VARCHAR;

//    /**
//     * <P>The constant in the Java programming language, sometimes
referred
//     * to as a type code, that identifies the recent SQL 2003 SQL type
//     * <code>XML</code>.
//     *
//     * @since SQL 2003
//     * @deprectated
//     * @see #SQLXML
//     */
//    public static final int XML = 137;
    //------------------------- JDBC 4.0 -----------------------------------

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
<code>ROWID</code>
     *
     * @since JDK 1.6, HSQLDB 1.8.x
     *
     */
    public final static int ROWID = 2008;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
<code>NCHAR</code>
     *
     * @since JDK 1.6, HSQLDB 1.8.x
     */
    public static final int NCHAR = -8;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
<code>NVARCHAR</code>.
     *
     * @since JDK 1.6, HSQLDB 1.8.x
     */
    public static final int NVARCHAR = -9;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
<code>LONGNVARCHAR</code>.
     *
     * @since JDK 1.6, HSQLDB 1.8.x
     */
    public static final int LONGNVARCHAR = -10;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
<code>NCLOB</code>.
     *
     * @since JDK 1.6, HSQLDB 1.8.x
     */
    public static final int NCLOB = 2007;

    /**
     * The constant in the Java programming language, sometimes referred to
     * as a type code, that identifies the generic SQL type
<code>XML</code>.
     *
     * @since JDK 1.6, HSQLDB 1.8.x
     */
    public static final int SQLXML = 2009;

    //----------------------------- End JDBC 4.0
-------------------------------

    /**
     * The default HSQLODB type sub-identifier. This indicates that an
     * HSQLDB type with this sub-type, if supported, is the very closest
     * thing HSQLDB offerers to the JDBC/SQL2003 type
     */
    public static final int TYPE_SUB_DEFAULT = 1;

    /**
     * The IGNORECASE type sub-identifier. This indicates that an HSQLDB
type
     * with this sub-type, if supported,  is the closest thing HSQLDB
offerers
     * to the JDBC/SQL2003 type, except that case is ignored in comparisons
     */
    public static final int TYPE_SUB_IGNORECASE = TYPE_SUB_DEFAULT << 2;

    /**
     * Every (type,type-sub) combination known in the HSQLDB context.
     * Not every combination need be supported as a table or procedure
     * column type -- such determinations are handled in DITypeInfo.
     */
    public static final int[][] ALL_TYPES = {
        {
            SQL_ARRAY, TYPE_SUB_DEFAULT
        }, {
            SQL_BIGINT, TYPE_SUB_DEFAULT
        }, {
            SQL_BINARY, TYPE_SUB_DEFAULT
        }, {
            SQL_VARBINARY, TYPE_SUB_DEFAULT
        }, {
            SQL_BLOB, TYPE_SUB_DEFAULT
        }, {
            SQL_BOOLEAN, TYPE_SUB_DEFAULT
        }, {
            SQL_CHAR, TYPE_SUB_DEFAULT
        }, {
            SQL_CLOB, TYPE_SUB_DEFAULT
        }, {
            DATALINK, TYPE_SUB_DEFAULT
        }, {
            SQL_DATE, TYPE_SUB_DEFAULT
        }, {
            SQL_DECIMAL, TYPE_SUB_DEFAULT
        }, {
            DISTINCT, TYPE_SUB_DEFAULT
        }, {
            SQL_DOUBLE, TYPE_SUB_DEFAULT
        }, {
            SQL_FLOAT, TYPE_SUB_DEFAULT
        }, {
            SQL_INTEGER, TYPE_SUB_DEFAULT
        }, {
            JAVA_OBJECT, TYPE_SUB_DEFAULT
        }, {
            SQL_NCHAR, TYPE_SUB_DEFAULT
        }, {
            NCLOB, TYPE_SUB_DEFAULT
        }, {
            SQL_ALL_TYPES, TYPE_SUB_DEFAULT
        }, {
            SQL_NUMERIC, TYPE_SUB_DEFAULT
        }, {
            SQL_NVARCHAR, TYPE_SUB_DEFAULT
        }, {
            OTHER, TYPE_SUB_DEFAULT
        }, {
            SQL_REAL, TYPE_SUB_DEFAULT
        }, {
            SQL_REF, TYPE_SUB_DEFAULT
        }, {
            ROWID, TYPE_SUB_DEFAULT
        }, {
            SQL_SMALLINT, TYPE_SUB_DEFAULT
        }, {
            STRUCT, TYPE_SUB_DEFAULT
        }, {
            SQL_TIME, TYPE_SUB_DEFAULT
        }, {
            SQL_TIMESTAMP, TYPE_SUB_DEFAULT
        }, {
            TINYINT, TYPE_SUB_DEFAULT
        }, {
            SQL_VARCHAR, TYPE_SUB_DEFAULT
        }, {
            SQL_VARCHAR, TYPE_SUB_IGNORECASE
        }, {
            SQL_XML, TYPE_SUB_DEFAULT
        }
    };

// lookup for types
    final static IntValueHashMap javaTypeNumbers;

//  boucherb@users - We can't handle method invocations in
//                   Function.java whose number class is
//                   narrower than the corresponding internal
//                   wrapper
    private final static HashSet illegalParameterClasses;

    static {
        javaTypeNumbers = new IntValueHashMap(32);

        javaTypeNumbers.put("int", Types.SQL_INTEGER);
        javaTypeNumbers.put("java.lang.Integer", Types.SQL_INTEGER);
        javaTypeNumbers.put("double", Types.SQL_DOUBLE);
        javaTypeNumbers.put("java.lang.Double", Types.SQL_DOUBLE);
        javaTypeNumbers.put("java.lang.String", Types.SQL_VARCHAR);
        javaTypeNumbers.put(DateClassName, Types.SQL_DATE);
        javaTypeNumbers.put(TimeClassName, Types.SQL_TIME);
        javaTypeNumbers.put(TimestampClassName, Types.SQL_TIMESTAMP);
        javaTypeNumbers.put("java.util.Date", Types.SQL_DATE);
        javaTypeNumbers.put(DecimalClassName, Types.SQL_DECIMAL);
        javaTypeNumbers.put("boolean", Types.SQL_BOOLEAN);
        javaTypeNumbers.put("java.lang.Boolean", Types.SQL_BOOLEAN);
        javaTypeNumbers.put("byte", Types.TINYINT);
        javaTypeNumbers.put("java.lang.Byte", Types.TINYINT);
        javaTypeNumbers.put("short", Types.SQL_SMALLINT);
        javaTypeNumbers.put("java.lang.Short", Types.SQL_SMALLINT);
        javaTypeNumbers.put("long", Types.SQL_BIGINT);
        javaTypeNumbers.put("java.lang.Long", Types.SQL_BIGINT);
        javaTypeNumbers.put("[B", Types.SQL_BINARY);
        javaTypeNumbers.put("java.lang.Object", Types.OTHER);
        javaTypeNumbers.put("java.lang.Void", Types.SQL_ALL_TYPES);

        //
        illegalParameterClasses = new org.hsqldb.lib.HashSet();

        illegalParameterClasses.add(Byte.TYPE);
        illegalParameterClasses.add(Short.TYPE);
        illegalParameterClasses.add(Float.TYPE);
        illegalParameterClasses.add(Byte.class);
        illegalParameterClasses.add(Short.class);
        illegalParameterClasses.add(Float.class);

        //
    }

    /**
     * Returns SQL type string for a java.sql.Types int value
     */
/*
    public static String getTypeString(int type, int precision, int scale) {

        String s = (String) typeNames.get(type);

        if (precision != 0 && acceptsPrecisionCreateParam(type)) {
            StringBuffer sb = new StringBuffer(s);

            sb.append(Token.T_OPENBRACKET);
            sb.append(precision);

            if (scale != 0 && acceptsScaleCreateParam(type)) {
                sb.append(Token.T_COMMA);
                sb.append(scale);
            }

            sb.append(Token.T_CLOSEBRACKET);

            return sb.toString();
        }

        return s;
    }
*/

    /**
     * Retieves the type number corresponding to the class
     * of an IN, IN OUT or OUT parameter.  <p>
     *
     * This method extends getTypeNr to return OTHER for
     * primitive arrays, classes that directly implement
     * java.io.Serializable and non-primitive arrays whose
     * base component implements java.io.Serializable,
     * allowing, for instance, arguments and return types of
     * primitive arrays, Serializable objects and arrays,
     * of Serializable objects.  Direct primitive types
     * other than those mapping directly to the internal
     * wrapper form are not yet handled.  That is, HSQLDB
     * cannot yet properly deal with CALLs involving methods
     * with primitive byte, short, float or their
     * corresponding wrappers, due to the way internal
     * conversion works and lack of detection and narrowing
     * code in Function to allow this.  In other words,
     * passing in or retrieving any of the mentioned types
     * always causes conversion to a wider internal wrapper
     * which is genrally incompatible under reflective
     * invocation, resulting in an IllegalArgumentException.
     *
     * @param  c a Class instance
     * @return java.sql.Types int value
     * @throws  HsqlException
     */
    static int getParameterSQLTypeNumber(Class c) {

        String name;
        int    type;

        if (c == null) {
            throw Error.runtimeError(ErrorCode.U_S0500, "Types");
        }

        if (Void.TYPE.equals(c)) {
            return Types.SQL_ALL_TYPES;
        }

        name = c.getName();
        type = javaTypeNumbers.get(name, Integer.MIN_VALUE);

        if (type == Integer.MIN_VALUE) {

            // byte[] is already covered as BINARY in typeAliases
            if (c.isArray()) {
                while (c.isArray()) {
                    c = c.getComponentType();
                }

                if (c.isPrimitive()
                        || java.io.Serializable.class.isAssignableFrom(c)) {
                    type = OTHER;
                }
            } else if (java.io.Serializable.class.isAssignableFrom(c)) {
                type = OTHER;
            }
        }

        if (type == Integer.MIN_VALUE) {
            throw Error.error(ErrorCode.X_42561);
        }

        return type;
    }

    public static boolean acceptsZeroPrecision(int type) {

        switch (type) {

            case Types.SQL_TIME :
            case Types.SQL_TIMESTAMP :
                return true;

            default :
                return false;
        }
    }

    public static boolean requiresPrecision(int type) {

        switch (type) {

            case Types.SQL_BIT_VARYING :
            case Types.SQL_VARBINARY :
            case Types.SQL_VARCHAR :
            case Types.SQL_NVARCHAR :
            case Types.VARCHAR_IGNORECASE :
                return true;

            default :
                return false;
        }
    }

    /**
     * Types that accept precision params in column definition or casts.
     * CHAR, VARCHAR and VARCHAR_IGNORECASE params
     * are ignored when the sql.enforce_strict_types is false.
     *
     */
    public static boolean acceptsPrecision(int type) {

        switch (type) {

            case Types.LONGVARCHAR :
            case Types.LONGVARBINARY :
            case Types.SQL_BINARY :
            case Types.SQL_BIT :
            case Types.SQL_BIT_VARYING :
            case Types.SQL_BLOB :
            case Types.SQL_CHAR :
            case Types.SQL_NCHAR :
            case Types.SQL_CLOB :
            case Types.NCLOB :
            case Types.SQL_VARBINARY :
            case Types.SQL_VARCHAR :
            case Types.SQL_NVARCHAR :
            case Types.VARCHAR_IGNORECASE :
            case Types.SQL_DECIMAL :
            case Types.SQL_NUMERIC :
            case Types.SQL_FLOAT :
            case Types.SQL_TIME :
            case Types.SQL_TIMESTAMP :
            case Types.SQL_INTERVAL_YEAR :
            case Types.SQL_INTERVAL_YEAR_TO_MONTH :
            case Types.SQL_INTERVAL_MONTH :
            case Types.SQL_INTERVAL_DAY :
            case Types.SQL_INTERVAL_DAY_TO_HOUR :
            case Types.SQL_INTERVAL_DAY_TO_MINUTE :
            case Types.SQL_INTERVAL_DAY_TO_SECOND :
            case Types.SQL_INTERVAL_HOUR :
            case Types.SQL_INTERVAL_HOUR_TO_MINUTE :
            case Types.SQL_INTERVAL_HOUR_TO_SECOND :
            case Types.SQL_INTERVAL_MINUTE :
            case Types.SQL_INTERVAL_MINUTE_TO_SECOND :
            case Types.SQL_INTERVAL_SECOND :
                return true;

            default :
                return false;
        }
    }

    public static boolean acceptsScaleCreateParam(int type) {

        switch (type) {

            case Types.SQL_INTERVAL_SECOND :
                return true;

            case Types.SQL_DECIMAL :
            case Types.SQL_NUMERIC :
                return true;

            default :
                return false;
        }
    }

    public static String getTypeName(int type) {

        switch (type) {

            case Types.SQL_ARRAY :
                return "ARRAY";

            case Types.SQL_BIGINT :
                return "BIGINT";

            case Types.SQL_BINARY :
                return "BINARY";

            case Types.SQL_BLOB :
                return "BLOB";

            case Types.SQL_BOOLEAN :
                return "BOOLEAN";

            case Types.SQL_CHAR :
                return "CHAR";

            case Types.SQL_NCHAR :
                return "NCHAR";

            case Types.SQL_CLOB :
                return "CLOB";

            case Types.NCLOB :
                return "NCLOB";

            case Types.SQL_DATALINK :
                return "DATALINK";

            case Types.SQL_DATE :
                return "DATE";

            case Types.SQL_DECIMAL :
                return "DECIMAL";

            case Types.DISTINCT :
                return "DISTINCT";

            case Types.SQL_DOUBLE :
                return "DOUBLE";

            case Types.SQL_FLOAT :
                return "FLOAT";

            case Types.SQL_INTEGER :
                return "INTEGER";

            case Types.JAVA_OBJECT :
                return "JAVA_OBJECT";

            case Types.SQL_ALL_TYPES :
                return "NULL";

            case Types.SQL_NUMERIC :
                return "NUMERIC";

            case Types.OTHER :
                return "OTHER";

            case Types.SQL_REAL :
                return "REAL";

            case Types.SQL_REF :
                return "REF";

            case Types.ROWID :
                return "ROWID";

            case Types.SQL_SMALLINT :
                return "SMALLINT";

            case Types.STRUCT :
                return "STRUCT";

            case Types.SQL_TIME :
                return "TIME";

            case Types.SQL_TIMESTAMP :
                return "TIMESTAMP";

            case Types.TINYINT :
                return "TINYINT";

            case Types.SQL_VARBINARY :
                return "VARBINARY";

            case Types.SQL_VARCHAR :
                return "VARCHAR";

            case Types.SQL_NVARCHAR :
                return "NVARCHAR";

            case Types.VARCHAR_IGNORECASE :
                return "VARCHAR_IGNORECASE";

            case Types.SQL_XML :
                return "XML";

            default :
                return null;
        }
    }

    /**
     * A reasonable/customizable number to avoid the shortcomings/defects
     * associated with doing a dynamic scan of results to determine
     * the value.  In practice, it turns out that single query yielding
     * widely varying values for display size of CHAR and VARCHAR columns
     * on repeated execution results in patently poor usability, as some
fairly
     * high-profile, otherwise "enterprise-quality" RAD tools depend on
     * on the first value returned to lay out forms and limit the size of
     * single line edit controls, set corresponding local datastore storage
     * sizes, etc. In practice, It also turns out that many tools (due to
     * the original lack of PreparedStatement.getMetaData() in JDK 1.1)
emulate
     * a SQL_DESCRIBE by executing a query hopefully guaranteed to return no
     * or very few rows for example: select ... from ... where 1=0.
     * Using the dynamic scan of 1.7.2 RC5 and previous, therefore, the
     * minimum display size value (1) was often being generated during
     * a tool's describe phase.  Upon subsequent "real" retrievals, some
     * tools complain that CHAR and VARCHAR result values exceeded the
     * originally reported display size and refused to fetch further values.
     */
    public static final int MAX_CHAR_OR_VARCHAR_DISPLAY_SIZE =
        MAX_CHAR_OR_VARCHAR_DISPLAY_SIZE();

    // So that the variable can be both public static final and
    // customizable through system properties if required.
    //
    // 32766 (0x7ffe) seems to be a magic number over which several
    // rather high-profile RAD tools start to have problems
    // regarding layout and allocation stress.  It is gently
    // recommended that LONGVARCHAR be used for larger values in RAD
    // tool layout & presentation use cases until such time as we provide
    // true BLOB support (at which point, LONGVARCHAR will most likely
become
    // an alias for CLOB).
    //
    // Most GUI tools seem to handle LONGVARCHAR gracefully by:
    //
    // 1.) refusing to directly display such columns in graphical query
results
    // 2.) providing other means to retrieve and display such values
    private static int MAX_CHAR_OR_VARCHAR_DISPLAY_SIZE() {

        try {
            return Integer.getInteger(

 HsqlDatabaseProperties.system_max_char_or_varchar_display_size,
                32766).intValue();
        } catch (SecurityException e) {
            return 32766;
        }
    }

    public static int getMaxDisplaySize(int type) {

        switch (type) {

            case Types.SQL_BLOB :
            case Types.SQL_CLOB :
                return Integer.MAX_VALUE;

            case Types.SQL_BINARY :
            case Types.SQL_LONGVARBINARY :
            case Types.OTHER :
            case Types.SQL_VARBINARY :
            case Types.SQL_XML :
            case Types.ROWID :
                return Integer.MAX_VALUE;    // max string length

            case Types.SQL_CHAR :
            case Types.SQL_NCHAR :
            case Types.SQL_VARCHAR :
            case Types.SQL_NVARCHAR :
                return MAX_CHAR_OR_VARCHAR_DISPLAY_SIZE;

            case Types.SQL_BIGINT :          // PowerBuilder barfs, wants 19

                // ...not our problem, tho,
                // according to JDBC
                return 20;                   // precision + "-".length();

            case Types.SQL_BOOLEAN :
                return 5;                    //
Math.max("true".length(),"false".length);

            case Types.SQL_DATALINK :
                return 20004;                // same as precision

            case Types.SQL_DECIMAL :
            case Types.SQL_NUMERIC :
                return 646456995;            // precision + "-.".length()

            case Types.SQL_DATE :
                return 10;                   // same as precision

            case Types.SQL_INTEGER :
                return 11;                   // precision + "-".length();

            case Types.SQL_FLOAT :
            case Types.SQL_REAL :
            case Types.SQL_DOUBLE :
                return 23;                   //
String.valueOf(-Double.MAX_VALUE).length();

            case Types.SQL_TIME :
                return 8;                    // same as precision

            case Types.SQL_SMALLINT :
                return 6;                    // precision + "-".length();

            case Types.SQL_TIMESTAMP :
                return 29;                   // same as precision

            case Types.TINYINT :
                return 4;                    // precision + "-".length();

            default :
                return 0;                    // unknown
        }
    }

    public static boolean isSearchable(int type) {

        switch (type) {

            case Types.SQL_ARRAY :
            case Types.SQL_BLOB :
            case Types.SQL_CLOB :
            case Types.NCLOB :
            case Types.JAVA_OBJECT :
            case Types.STRUCT :
            case Types.OTHER :
            case Types.ROWID :
                return false;

            default :
                return true;
        }
    }

    public static Boolean isCaseSensitive(int type) {

        switch (type) {

            case Types.SQL_ARRAY :
            case Types.SQL_BLOB :
            case Types.SQL_CLOB :
            case Types.NCLOB :
            case Types.DISTINCT :
            case Types.JAVA_OBJECT :
            case Types.SQL_ALL_TYPES :
            case Types.SQL_REF :
            case Types.STRUCT :
            case Types.ROWID :
                return null;

            case Types.SQL_CHAR :
            case Types.SQL_NCHAR :
            case Types.SQL_DATALINK :
            case Types.SQL_VARCHAR :
            case Types.SQL_NVARCHAR :
            case Types.OTHER :
            case Types.SQL_XML :
                return Boolean.TRUE;

            case Types.VARCHAR_IGNORECASE :
            default :
                return Boolean.FALSE;
        }
    }

    public static Boolean isUnsignedAttribute(int type) {

        switch (type) {

            case Types.SQL_BIGINT :
            case Types.SQL_DECIMAL :
            case Types.SQL_DOUBLE :
            case Types.SQL_FLOAT :
            case Types.SQL_INTEGER :
            case Types.SQL_NUMERIC :
            case Types.SQL_REAL :
            case Types.SQL_SMALLINT :
            case Types.TINYINT :
                return Boolean.FALSE;

            default :
                return null;
        }
    }

    public static int getPrecision(int type) {

        switch (type) {

            case Types.SQL_BLOB :
            case Types.SQL_CLOB :
                return Integer.MAX_VALUE;

            case Types.SQL_BINARY :
            case Types.SQL_CHAR :
            case Types.SQL_NCHAR :
            case Types.OTHER :
            case Types.SQL_VARBINARY :
            case Types.SQL_VARCHAR :
            case Types.SQL_NVARCHAR :
            case Types.SQL_XML :
                return Integer.MAX_VALUE;

            case Types.SQL_BIGINT :
                return 19;

            case Types.SQL_BOOLEAN :
                return 1;

            case Types.DATALINK :

                // from SQL CLI spec.  TODO:  Interpretation?
                return 20004;

            case Types.SQL_DECIMAL :
            case Types.SQL_NUMERIC :

// Integer.MAX_VALUE bit 2's complement number:
// (Integer.MAX_VALUE-1) / ((ln(10)/ln(2)) bits per decimal digit)
// See:  java.math.BigInteger
// - the other alternative is that we could report the numprecradix as 2 and
// report Integer.MAX_VALUE here
                return 646456993;

            case Types.SQL_DATE :
            case Types.SQL_INTEGER :
                return 10;

            case Types.SQL_FLOAT :
                return 53;    // Oops...52 in memory + 1 implicit bit

            case Types.SQL_REAL :
            case Types.SQL_DOUBLE :
                return 17;

            case Types.SQL_TIME :
                return 8;

            case Types.SQL_SMALLINT :
                return 5;

            case Types.SQL_TIMESTAMP :
                return 29;

            case Types.TINYINT :
                return 3;

            default :
                return 0;
        }
    }

    public static String getColStClsName(int type) {

        switch (type) {

            case Types.SQL_BLOB :
                return BlobClassName;

            case Types.SQL_CLOB :
                return ClobClassName;

            case Types.SQL_BIGINT :
                return "java.lang.Long";

            case Types.SQL_BINARY :
            case Types.SQL_VARBINARY :

                // but wrapped by org.hsqldb.Binary
                return "[B";

            case Types.OTHER :

                // but wrapped by org.hsqldb.JavaObject
                return "java.lang.Object";

            case Types.SQL_BOOLEAN :
                return "java.lang.Boolean";

            case Types.SQL_CHAR :
            case Types.SQL_NCHAR :
            case Types.SQL_VARCHAR :
            case Types.SQL_NVARCHAR :
            case Types.SQL_XML :    //?
                return "java.lang.String";

            case Types.SQL_DATALINK :
                return "java.net.URL";

            case Types.SQL_DATE :
                return DateClassName;

            case Types.SQL_DECIMAL :
            case Types.SQL_NUMERIC :
                return DecimalClassName;

            case Types.SQL_DOUBLE :
            case Types.SQL_FLOAT :
            case Types.SQL_REAL :
                return "java.lang.Double";

            case Types.SQL_INTEGER :
            case Types.SQL_SMALLINT :
            case Types.TINYINT :
                return "java.lang.Integer";

            case Types.SQL_TIME :
                return TimeClassName;

            case Types.SQL_TIMESTAMP :
                return TimestampClassName;

            default :
                return null;
        }
    }
}



    About JDBC connection stuff:



org.hsqldb.jdbc.JDBCConnection:

//#endif JAVA6



    /**

     * Constructs an object that implements the <code>SQLXML</code>
interface. The object

     * returned initially contains no data. The
<code>createXmlStreamWriter</code> object and

     * <code>setString</code> method of the <code>SQLXML</code> interface
may be used to add data to the <code>SQLXML</code>

     * object.

     * @return An object that implements the <code>SQLXML</code> interface

     * @throws SQLException if an object that implements the
<code>SQLXML</code> interface can not

     * be constructed, this method is

     * called on a closed connection or a database access error occurs.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this data type

     * @since JDK 1.6, HSQLDB 1.9.0

     */

//#ifdef JAVA6

    *public SQLXML createSQLXML() throws SQLException* {



        checkClosed();



        return new JDBCSQLXML();

    }



//#endif JAVA6


The main file - org.hsqldb.jdbc.JDBCSQLXML.java:


public class JDBCSQLXML implements SQLXML {



    private static String domFeatures = "XML 3.0 Traversal +Events 2.0";

    private static DOMImplementation         domImplementation;

    private static DOMImplementationRegistry domImplementationRegistry;

    private static ThreadPoolExecutor        executorService;

    private static Transformer               identityTransformer;

    private static TransformerFactory        transformerFactory;



    /**

     * Precomputed Charset to reduce octect to character sequence conversion

     * charset lookup overhead.

     */

    private static final Charset                utf8Charset;

    private static ArrayBlockingQueue<Runnable> workQueue;



    static {

        Charset charset = null;



        try {

            charset = Charset.forName("UTF8");

        } catch (Exception e) {

        }

        utf8Charset = charset;

    }



    /**

     * When non-null, the SAX ContentHandler currently in use to build this

     * object's SQLXML value from a SAX event sequence.

     */

    private SAX2DOMBuilder builder;



    /**

     * Whether this object is closed.  When closed, no further reading

     * or writing is possible.

     */

    private boolean closed;



    // ------------------------- Internal Implementation
-----------------------



    /**

     * This object's SQLXML value as a GZIPed byte array

     */

    private volatile byte[] gzdata;



    /**

     * When non-null, the stream currently in use to read this object's

     * SQLXML value as an octet sequence.

     */

    private InputStream inputStream;



    /**

     * When non-null, the stream currently in use to write this object's

     * SQLXML value from an octet sequence.

     */

    private ClosableByteArrayOutputStream outputStream;



    /**

     * This object's public id

     */

    private String publicId;



    /**

     * Whether it is possible to read this object's SQLXML value.

     */

    private boolean readable;



    /**

     * This object's system id

     */

    private String systemId;



    /**

     * Whether it is possible to write this object's SQLXML value.

     */

    private boolean writable;



    /**

     * Constructs a new, initially write-only JDBCSQLXML object. <p>

     */

    protected JDBCSQLXML() {

        setReadable(false);

        setWritable(true);

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given octet

     * sequence. <p>

     *

     * @param bytes the octet sequence representing the SQLXML value

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(byte[] bytes) throws SQLException {

        this(bytes, null);

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given character

     * sequence. <p>

     *

     * @param chars the character sequence representing the SQLXML value

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(char[] chars) throws SQLException {

        this(chars, 0, chars.length, null);

    }



    /**

     * Constructs a new JDBCSQLXML object from the given Document. <p>

     *

     * @param document the Document representing the SQLXML value

     * @throws java.sql.SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(Document document) throws SQLException {

        this(new DOMSource(document));

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given octet

     * sequence. <p>

     *

     * Relative URI references will be resolved against the present working

     * directory reported by the Java virtual machine. <p>

     *

     * @param inputStream an octet stream representing an SQLXML value

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(InputStream inputStream) throws SQLException {

        this(inputStream, null);

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given character

     * sequence. <p>

     *

     * Relative URI references will be resolved against the present working

     * directory reported by the Java virtual machine. <p>

     *

     * <b>Note:</b>Normally, a byte stream should be used rather than a
reader,

     * so that the XML parser can resolve character encoding specified by
the

     * XML declaration. However, in many cases the encoding of the input
stream

     * is already resolved, as in the case of reading XML from a
StringReader.

     *

     * @param reader a character stream representing an SQLXML value

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(Reader reader) throws SQLException {

        this(reader, null);

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given Source

     * object. <p>

     *

     * @param source a Source representing an SQLXML value

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    public JDBCSQLXML(Source source) throws SQLException {

        init(source);

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given character

     * sequence. <p>

     *

     * Relative URI references will be resolved against the present working

     * directory reported by the Java virtual machine. <p>

     *

     * @param string a character sequence representing an SQLXML value

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(String string) throws SQLException {

        this(new StreamSource(new StringReader(string)));

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given octet

     * sequence. <p>

     *

     * @param bytes the octet sequence representing the SQLXML value

     * @param systemId must be a String that conforms to the URI syntax;

     *        allows relative URIs to be processed.

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(byte[] bytes, String systemId) throws SQLException
{

        this(new StreamSource(new ByteArrayInputStream(bytes), systemId));

    }



    protected JDBCSQLXML(char[] chars, String systemId) throws SQLException
{

        this(chars, 0, chars.length, systemId);

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given octet

     * sequence. <p>

     *

     * Relative URI references will be resolved against the given systemId.
<p>

     *

     * @param inputStream an octet stream representing an SQLXML value

     * @param systemId a String that conforms to the URI syntax, indicating

     *      the URI from which the XML data is being read, so that relative
URI

     *      references can be resolved

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(InputStream inputStream,

                         String systemId) throws SQLException {

        this(new StreamSource(inputStream, systemId));

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given character

     * sequence. <p>

     *

     * Relative URI references will be resolved against the given systemId.
<p>

     *

     * <b>Note:</b>Normally, a byte stream should be used rather than a
reader,

     * so that the XML parser can resolve character encoding specified by
the

     * XML declaration. However, in many cases the encoding of the input
stream

     * is already resolved, as in the case of reading XML from a
StringReader.

     *

     * @param reader a character stream representing an SQLXML value;

     * @param systemId a String that conforms to the URI syntax, indicating

     *      the URI from which the XML data is being read, so that relative
URI

     *      references can be resolved

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(Reader reader, String systemId) throws SQLException
{

        this(new StreamSource(reader, systemId));

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given character

     * sequence. <p>

     *

     * Relative URI references will be resolved against the given systemId.
<p>

     *

     * @param string a character sequence representing an SQLXML value

     * @param systemId a String that conforms to the URI syntax, indicating

     *      the URI from which the XML data is being read, so that relative
URI

     *      references can be resolved

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(String string, String systemId) throws SQLException
{

        this(new StreamSource(new StringReader(string), systemId));

    }



    /**

     * Constructs a new read-only JDBCSQLXML object from the given gzipped
octet

     * sequence. <p>

     *

     * @param bytes the gzipped octet sequence representing the SQLXML value

     * @param clone whether to clone the given gzipped octet sequence

     * @param systemId

     * @param publicId

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected JDBCSQLXML(byte[] bytes, boolean clone, String systemId,

                         String publicId) throws SQLException {



        this.setGZipData(clone ? bytes.clone()

                               : bytes);



        this.systemId = systemId;

        this.publicId = publicId;

    }



    protected JDBCSQLXML(char[] chars, int offset, int length,

                         String systemId) throws SQLException {

        this(new StreamSource(new CharArrayReader(chars, offset, length),

                              systemId));

    }



    /**

     * This method closes this object and releases the resources that it
held.

     * The SQL XML object becomes invalid and neither readable or writeable

     * when this method is called.

     *

     * After <code>free</code> has been called, any attempt to invoke a

     * method other than <code>free</code> will result in a
<code>SQLException</code>

     * being thrown.  If <code>free</code> is called multiple times, the
subsequent

     * calls to <code>free</code> are treated as a no-op.

     * @throws SQLException if there is an error freeing the XML value.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6

     */

    public void free() throws SQLException {

        close();

    }



    /**

     * Retrieves the XML value designated by this SQLXML instance as a
stream.

     * The bytes of the input stream are interpreted according to appendix F
of the XML 1.0 specification.

     * The behavior of this method is the same as
ResultSet.getBinaryStream()

     * when the designated column of the ResultSet has a type java.sql.Types
of SQLXML.

     * <p>

     * The SQL XML object becomes not readable when this method is called
and

     * may also become not writable depending on implementation.

     *

     * @return a stream containing the XML data.

     * @throws SQLException if there is an error processing the XML value.

     *   An exception is thrown if the state is not readable.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6

     */

    public synchronized InputStream getBinaryStream() throws SQLException {



        checkClosed();

        checkReadable();



        InputStream inputStream = getBinaryStreamImpl();



        setReadable(false);

        setWritable(false);



        return inputStream;

    }



    /**

     * Retrieves a stream that can be used to write the XML value that this
SQLXML instance represents.

     * The stream begins at position 0.

     * The bytes of the stream are interpreted according to appendix F of
the XML 1.0 specification

     * The behavior of this method is the same as
ResultSet.updateBinaryStream()

     * when the designated column of the ResultSet has a type java.sql.Types
of SQLXML.

     * <p>

     * The SQL XML object becomes not writeable when this method is called
and

     * may also become not readable depending on implementation.

     *

     * @return a stream to which data can be written.

     * @throws SQLException if there is an error processing the XML value.

     *   An exception is thrown if the state is not writable.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6

     */

    public synchronized OutputStream setBinaryStream() throws SQLException {



        checkClosed();

        checkWritable();



        OutputStream outputStream = setBinaryStreamImpl();



        setWritable(false);

        setReadable(true);



        return outputStream;

    }



    /**

     * Retrieves the XML value designated by this SQLXML instance as a
java.io.Reader object.

     * The format of this stream is defined by org.xml.sax.InputSource,

     * where the characters in the stream represent the unicode code points
for

     * XML according to section 2 and appendix B of the XML 1.0
specification.

     * Although an encoding declaration other than unicode may be present,

     * the encoding of the stream is unicode.

     * The behavior of this method is the same as
ResultSet.getCharacterStream()

     * when the designated column of the ResultSet has a type java.sql.Types
of SQLXML.

     * <p>

     * The SQL XML object becomes not readable when this method is called
and

     * may also become not writable depending on implementation.

     *

     * @return a stream containing the XML data.

     * @throws SQLException if there is an error processing the XML value.

     *   The getCause() method of the exception may provide a more detailed
exception, for example,

     *   if the stream does not contain valid characters.

     *   An exception is thrown if the state is not readable.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6

     */

    public synchronized Reader getCharacterStream() throws SQLException {



        checkClosed();

        checkReadable();



        Reader reader = getCharacterStreamImpl();



        setReadable(false);

        setWritable(false);



        return reader;

    }



    /**

     * Retrieves a stream to be used to write the XML value that this SQLXML
instance represents.

     * The format of this stream is defined by org.xml.sax.InputSource,

     * where the characters in the stream represent the unicode code points
for

     * XML according to section 2 and appendix B of the XML 1.0
specification.

     * Although an encoding declaration other than unicode may be present,

     * the encoding of the stream is unicode.

     * The behavior of this method is the same as
ResultSet.updateCharacterStream()

     * when the designated column of the ResultSet has a type java.sql.Types
of SQLXML.

     * <p>

     * The SQL XML object becomes not writeable when this method is called
and

     * may also become not readable depending on implementation.

     *

     * @return a stream to which data can be written.

     * @throws SQLException if there is an error processing the XML value.

     *   The getCause() method of the exception may provide a more detailed
exception, for example,

     *   if the stream does not contain valid characters.

     *   An exception is thrown if the state is not writable.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6 Build 79

     */

    public synchronized Writer setCharacterStream() throws SQLException {



        checkClosed();

        checkWritable();



        Writer writer = setCharacterStreamImpl();



        setReadable(true);

        setWritable(false);



        return writer;

    }



    /**

     * Returns a string representation of the XML value designated by this
SQLXML instance.

     * The format of this String is defined by org.xml.sax.InputSource,

     * where the characters in the stream represent the unicode code points
for

     * XML according to section 2 and appendix B of the XML 1.0
specification.

     * Although an encoding declaration other than unicode may be present,

     * the encoding of the String is unicode.

     * The behavior of this method is the same as ResultSet.getString()

     * when the designated column of the ResultSet has a type java.sql.Types
of SQLXML.

     * <p>

     * The SQL XML object becomes not readable when this method is called
and

     * may also become not writable depending on implementation.

     *Hen

     * @return a string representation of the XML value designated by this
SQLXML instance.

     * @throws SQLException if there is an error processing the XML value.

     *   The getCause() method of the exception may provide a more detailed
exception, for example,

     *   if the stream does not contain valid characters.

     *   An exception is thrown if the state is not readable.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6

     */

    public synchronized String getString() throws SQLException {



        checkClosed();

        checkReadable();



        String value = getStringImpl();



        setReadable(false);

        setWritable(false);



        return value;

    }



    /**

     * Sets the XML value designated by this SQLXML instance to the given
String representation.

     * The format of this String is defined by org.xml.sax.InputSource,

     * where the characters in the stream represent the unicode code points
for

     * XML according to section 2 and appendix B of the XML 1.0
specification.

     * Although an encoding declaration other than unicode may be present,

     * the encoding of the String is unicode.

     * The behavior of this method is the same as ResultSet.updateString()

     * when the designated column of the ResultSet has a type java.sql.Types
of SQLXML.

     * <p>

     * The SQL XML object becomes not writeable when this method is called
and

     * may also become not readable depending on implementation.

     *

     * @param value the XML value

     * @throws SQLException if there is an error processing the XML value.

     *   The getCause() method of the exception may provide a more detailed
exception, for example,

     *   if the stream does not contain valid characters.

     *   An exception is thrown if the state is not writable.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6

     */

    public synchronized void setString(String value) throws SQLException {



        if (value == null) {

            throw Util.nullArgument("value");

        }

        checkWritable();

        setStringImpl(value);

        setReadable(true);

        setWritable(false);

    }



    /**

     * Returns a Source for reading the XML value designated by this SQLXML
instance.

     * Sources are used as inputs to XML parsers and XSLT transformers.

     * <p>

     * Sources for XML parsers will have namespace processing on by default.

     * The systemID of the Source is implementation dependent.

     * <p>

     * The SQL XML object becomes not readable when this method is called
and

     * may also become not writable depending on implementation.

     * <p>

     * Note that SAX is a callback architecture, so a returned

     * SAXSource should then be set with a content handler that will

     * receive the SAX events from parsing.  The content handler

     * will receive callbacks based on the contents of the XML.

     * <pre>

     *   SAXSource saxSource = sqlxml.getSource(SAXSource.class);

     *   XMLReader xmlReader = saxSource.getXMLReader();

     *   xmlReader.setContentHandler(myHandler);

     *   xmlReader.parse(saxSource.getInputSource());

     * </pre>

     *

     * @param sourceClass The class of the source, or null.

     * If the class is null, a vendor specifc Source implementation will be
returned.

     * The following classes are supported at a minimum:

     * <pre>

     *   javax.xml.transform.dom.DOMSource - returns a DOMSource

     *   javax.xml.transform.sax.SAXSource - returns a SAXSource

     *   javax.xml.transform.stax.StAXSource - returns a StAXSource

     *   javax.xml.transform.stream.StreamSource - returns a StreamSource

     * </pre>

     * @return a Source for reading the XML value.

     * @throws SQLException if there is an error processing the XML value

     *   or if this feature is not supported.

     *   The getCause() method of the exception may provide a more detailed
exception, for example,

     *   if an XML parser exception occurs.

     *   An exception is thrown if the state is not readable.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6 Build 79

     */

    @SuppressWarnings("unchecked")

    public synchronized <T extends Source>T getSource(

            Class<T> sourceClass) throws SQLException {



        checkClosed();

        checkReadable();



        final Source source = getSourceImpl(sourceClass);



        setReadable(false);

        setWritable(false);



        return (T) source;

    }



    /**

     * Returns a Result for setting the XML value designated by this SQLXML
instance.

     * <p>

     * The systemID of the Result is implementation dependent.

     * <p>

     * The SQL XML object becomes not writeable when this method is called
and

     * may also become not readable depending on implementation.

     * <p>

     * Note that SAX is a callback architecture and the returned

     * SAXResult has a content handler assigned that will receive the

     * SAX events based on the contents of the XML.  Call the content

     * handler with the contents of the XML document to assign the values.

     * <pre>

     *   SAXResult saxResult = sqlxml.getResult(SAXResult.class);

     *   ContentHandler contentHandler =
saxResult.getXMLReader().getContentHandler();

     *   contentHandler.startDocument();

     *   // set the XML elements and attributes into the result

     *   contentHandler.endDocument();

     * </pre>

     *

     * @param resultClass The class of the result, or null.

     * If resultClass is null, a vendor specific Result implementation will
be returned.

     * The following classes are supported at a minimum:

     * <pre>

     *   javax.xml.transform.dom.DOMResult - returns a DOMResult

     *   javax.xml.transform.sax.SAXResult - returns a SAXResult

     *   javax.xml.transform.stax.StAXResult - returns a StAXResult

     *   javax.xml.transform.stream.StreamResult - returns a StreamResult

     * </pre>

     * @return Returns a Result for setting the XML value.

     * @throws SQLException if there is an error processing the XML value

     *   or if this feature is not supported.

     *   The getCause() method of the exception may provide a more detailed
exception, for example,

     *   if an XML parser exception occurs.

     *   An exception is thrown if the state is not writable.

     * @exception SQLFeatureNotSupportedException if the JDBC driver does
not support

     * this method

     * @since JDK 1.6 Build 79

     */

    public synchronized <T extends Result>T setResult(

            Class<T> resultClass) throws SQLException {



        checkClosed();

        checkWritable();



        final T result = createResult(resultClass);



        setReadable(true);

        setWritable(false);



        return result;

    }



    /**

     * @return that may be used to perform processesing asynchronously.

     */

    protected static ExecutorService getExecutorService() {



        if (JDBCSQLXML.executorService == null) {

            int      corePoolSize    = 1;

            int      maximumPoolSize = 10;

            long     keepAliveTime   = 1;

            TimeUnit unit            = TimeUnit.SECONDS;



            JDBCSQLXML.workQueue = new ArrayBlockingQueue<Runnable>(10);

            JDBCSQLXML.executorService = new
ThreadPoolExecutor(corePoolSize,

                    maximumPoolSize, keepAliveTime, unit, workQueue);

        }



        return executorService;

    }



    /**

     * @return with which to obtain xml transformer instances.

     * @throws java.sql.SQLException when unable to obtain a factory
instance.

     */

    protected static TransformerFactory getTransformerFactory() throws
SQLException {



        if (JDBCSQLXML.transformerFactory == null) {

            try {

                JDBCSQLXML.transformerFactory =

                    TransformerFactory.newInstance();

            } catch (TransformerFactoryConfigurationError ex) {

                throw Exceptions.transformFailed(ex);

            }

        }



        return JDBCSQLXML.transformerFactory;

    }



    /**

     * @return used to perform identity transforms

     * @throws java.sql.SQLException when unable to obtain the instance.

     */

    protected static Transformer getIdentityTransformer() throws
SQLException {



        if (JDBCSQLXML.identityTransformer == null) {

            try {

                JDBCSQLXML.identityTransformer =

                    getTransformerFactory().newTransformer();

            } catch (TransformerConfigurationException ex) {

                throw Exceptions.transformFailed(ex);

            }

        }



        return JDBCSQLXML.identityTransformer;

    }



    /**

     * @return with which to construct DOM implementation instances.

     * @throws java.sql.SQLException when unable to obtain a factory
instance.

     */

    protected static DOMImplementationRegistry
getDOMImplementationRegistry() throws SQLException {



        if (domImplementationRegistry == null) {

            try {

                domImplementationRegistry =

                    DOMImplementationRegistry.newInstance();

            } catch (ClassCastException ex) {

                throw Exceptions.domInstantiation(ex);

            } catch (InstantiationException ex) {

                throw Exceptions.domInstantiation(ex);

            } catch (ClassNotFoundException ex) {

                throw Exceptions.domInstantiation(ex);

            } catch (IllegalAccessException ex) {

                throw Exceptions.domInstantiation(ex);

            }

        }



        return domImplementationRegistry;

    }



    /**

     * @return with which to create document instances.

     * @throws java.sql.SQLException when unable to obtain the DOM

     *         implementation instance.

     */

    protected static DOMImplementation getDOMImplementation() throws
SQLException {



        if (domImplementation == null) {

            domImplementation =

                getDOMImplementationRegistry().getDOMImplementation(

                    domFeatures);

        }



        if (domImplementation == null) {

            Exception ex = new RuntimeException("Not supported: "

                + domFeatures);



            throw Exceptions.domInstantiation(ex);

        }



        return domImplementation;

    }



    /**

     * @param namespaceURI of the document element to create or
<code>null</code>.

     * @param qualifiedName of the document element to be created or
<code>null</code>.

     * @param docType of document to be created or <code>null</code>.

     *   When <code>doctype</code> is not <code>null</code>, its

     *   <code>Node.ownerDocument</code> attribute is set to the document

     *   being created.

     * @return with its document element.

     *   If the <code>NamespaceURI</code>, <code>qualifiedName</code>, and

     *   <code>doctype</code> are <code>null</code>, the returned

     *   <code>Document</code> is empty with no document element.

     * @throws java.sql.SQLException wrapping any internal exception that
occurs.

     * @see
org.w3c.dom.DOMImplementation#createDocument(String,String,DocumentType)

     */

    protected static Document createDocument(String namespaceURI,

            String qualifiedName, DocumentType docType) throws SQLException
{



        try {

            return getDOMImplementation().createDocument(namespaceURI,

                    qualifiedName, docType);

        } catch (DOMException ex) {

            throw Exceptions.domInstantiation(ex);

        }

    }



    /**

     * @return that is empty with no document element.

     * @throws java.sql.SQLException wrapping any internal exception that
occurs.

     */

    protected static Document createDocument() throws SQLException {

        return createDocument(null, null, null);

    }



    /**

     * Initializes this object's SQLXML value from the given Source

     * object. <p>

     *

     * @param source the Source representing the SQLXML value

     * @throws SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected void init(Source source) throws SQLException {



        if (source == null) {

            throw Util.nullArgument("source");

        }



        Transformer           transformer =

            JDBCSQLXML.getIdentityTransformer();

        StreamResult          result      = new StreamResult();

        ByteArrayOutputStream baos        = new ByteArrayOutputStream();

        GZIPOutputStream      gzos;



        try {

            gzos = new GZIPOutputStream(baos);

        } catch (IOException ex) {

            throw Exceptions.transformFailed(ex);

        }

        result.setOutputStream(gzos);



        try {

            transformer.transform(source, result);

        } catch (TransformerException ex) {

            throw Exceptions.transformFailed(ex);

        }



        try {

            gzos.close();

        } catch (IOException ex) {

            throw Exceptions.transformFailed(ex);

        }



        byte[] data = baos.toByteArray();



        setGZipData(data);

        setReadable(true);

        setWritable(false);

    }



    /**

     * Assigns this object's SQLXML value from the designated gzipped array

     * of bytes.

     *

     * @param data the SQLXML value

     * @throws java.sql.SQLException if the argument does not represent a

     *      valid SQLXML value

     */

    protected void setGZipData(byte[] data) throws SQLException {



        if (data == null) {

            throw Util.nullArgument("data");

        }

        this.gzdata = data;

    }



    /**

     * Directly retrieves this object's present SQLMXL value as a gzipped

     * array of bytes. <p>

     *

     * May be null, empty or invalid.

     *

     * @return this object's SQLMXL value as a gzipped byte array

     */

    protected byte[] gZipData() {

        return this.gzdata;

    }



    /**

     * Retrieves this object's SQLXML value as a gzipped array of bytes,

     * possibly by terminating any in-progress write operations and
converting

     * accumulated intermediate data.

     *

     * @throws java.sql.SQLException if an underlying I/O or transform

     *      error occurs

     * @return this object's SQLXML value

     */

    protected byte[] getGZipData() throws SQLException {



        byte[] bytes = gZipData();



        if (bytes != null) {

            return bytes;

        }



        if ((this.outputStream == null) || !this.outputStream.isClosed()

                || this.outputStream.isFreed()) {

            throw Exceptions.notReadable();

        }



        try {

            setGZipData(this.outputStream.toByteArray());



            return gZipData();

        } catch (IOException ex) {

            throw Exceptions.notReadable();

        } finally {

            this.freeOutputStream();

        }

    }



    /**

     * closes this object and releases the resources that it holds.

     */

    protected synchronized void close() {



        this.closed = true;



        setReadable(false);

        setWritable(false);

        freeOutputStream();

        freeInputStream();



        this.gzdata = null;

    }



    /**

     * Closes the input stream, if any, currently in use to read this
object's

     * SQLXML value and nullifies the stream reference to make it elligible

     * for subsequent garbage collection.

     */

    protected void freeInputStream() {



        if (this.inputStream != null) {

            try {

                this.inputStream.close();

            } catch (IOException ex) {



                // ex.printStackTrace();

            } finally {

                this.inputStream = null;

            }

        }

    }



    /**

     * Closes the output stream, if any, currently in use to write this
object's

     * SQLXML value and nullifies the stream reference to make it elligible
for

     * subsequent garbage collection.  The stream's data buffer reference
may

     * also be nullified, in order to make it elligible for garbage
collection

     * immediately, just in case an external client still holds a reference
to

     * the output stream.

     */

    protected void freeOutputStream() {



        if (this.outputStream != null) {

            try {

                this.outputStream.free();

            } catch (IOException ex) {



                // ex.printStackTrace();

            }

            this.outputStream = null;

        }

    }



    /**

     * Checks whether this object is closed (has been freed).

     *

     * @throws java.sql.SQLException if this object is closed.

     */

    protected synchronized void checkClosed() throws SQLException {



        if (this.closed) {

            throw Exceptions.inFreedState();

        }

    }



    /**

     * Checks whether this object is readable.

     *

     * @throws java.sql.SQLException if this object is not readable.

     */

    protected synchronized void checkReadable() throws SQLException {



        if (!this.isReadable()) {

            throw Exceptions.notReadable();

        }

    }



    /**

     * Assigns this object's readability status.

     *

     * @param readable if <tt>true</tt>, then readable; else not readable

     */

    protected synchronized void setReadable(boolean readable) {

        this.readable = readable;

    }



    /**

     * Checks whether this object is writable.

     *

     * @throws java.sql.SQLException if this object is not writable.

     */

    protected synchronized void checkWritable() throws SQLException {



        if (!this.isWritable()) {

            throw Exceptions.notWritable();

        }

    }



    /**

     * Assigns this object's writability status.

     *

     * @param writable if <tt>true</tt>, then writable; else not writable

     */

    protected synchronized void setWritable(boolean writable) {

        this.writable = writable;

    }



    /**

     * Retrieves the object's readability status.

     *

     * @return if <tt>true</tt>, then readable; else not readable

     */

    public synchronized boolean isReadable() {

        return this.readable;

    }



    /**

     * Retrieves the object's readability status.

     *

     * @return if <tt>true</tt>, then writable; else not writable

     */

    public synchronized boolean isWritable() {

        return this.writable;

    }



    /**

     * Retrieves a stream representing the XML value designated by this

     * SQLXML instance. <p>

     *

     * @return a stream containing the XML data.

     * @throws SQLException if there is an error processing the XML value.

     */

    protected InputStream getBinaryStreamImpl() throws SQLException {



        try {

            return new GZIPInputStream(

                new ByteArrayInputStream(getGZipData()));

        } catch (IOException ex) {

            throw Exceptions.transformFailed(ex);

        }

    }



    /**

     * Retrieves a reader representing the XML value designated by this

     * SQLXML instance. <p>

     *

     * @return a reader containing the XML data.

     * @throws SQLException if there is an error processing the XML value.

     */

    protected Reader getCharacterStreamImpl() throws SQLException {

        return new InputStreamReader(getBinaryStreamImpl());

    }



    /**

     * Retrieves a string representing the XML value designated by this

     * SQLXML instance. <p>

     *

     * @return a string containing the XML data.

     * @throws SQLException if there is an error processing the XML value.

     */

    protected String getStringImpl() throws SQLException {



        try {

            return
StringConverter.inputStreamToString(getBinaryStreamImpl(),

                    "US-ASCII");

        } catch (IOException ex) {

            throw Exceptions.transformFailed(ex);

        }

    }



    /**

     * Retrieves a stream to completely write the XML value this SQLXML

     * instance represents. <p>

     *

     * @return a stream to which the data can be written.

     * @throws SQLException if there is an error processing the XML value.

     */

    protected OutputStream setBinaryStreamImpl() throws SQLException {



        this.outputStream = new ClosableByteArrayOutputStream();



        try {

            return new GZIPOutputStream(this.outputStream);

        } catch (IOException ex) {

            this.outputStream = null;



            throw Exceptions.resultInstantiation(ex);

        }

    }



    /**

     * Retrieves a writer to completely write the XML value this SQLXML

     * instance represents. <p>

     *

     * @return a writer to which the data can be written.

     * @throws SQLException if there is an error processing the XML value.

     *   The getCause() method of the exception may provide a more detailed
exception, for example,

     *   if the stream does not contain valid characters.

     *   An exception is thrown if the state is not writable.

     * @since JDK 1.6 Build 79

     */

    protected Writer setCharacterStreamImpl() throws SQLException {

        return new OutputStreamWriter(setBinaryStreamImpl());

    }



    /**

     * Sets the XML value designated by this SQLXML instance using the given

     * String representation. <p>

     *

     * @param value the XML value

     * @throws SQLException if there is an error processing the XML value.

     */

    protected void setStringImpl(String value) throws SQLException {

        init(new StreamSource(new StringReader(value)));

    }



    /**

     * Returns a Source for reading the XML value designated by this SQLXML

     * instance. <p>

     *

     * @param sourceClass The class of the source, or null.  If null, then a

     *      DOMSource is returned.

     * @return a Source for reading the XML value.

     * @throws SQLException if there is an error processing the XML value

     *   or if the given <tt>sourceClass</tt> is not supported.

     */

    protected <T extends Source>T getSourceImpl(

            Class<T> sourceClass) throws SQLException {



        if (JAXBSource.class.isAssignableFrom(sourceClass)) {



            // Must go first presently, since JAXBSource extends SAXSource

            // (purely as an implmentation detail) and it's not possible

            // to instantiate a valid JAXBSource with a Zero-Args

            // constructor(or any subclass thereof, due to the finality of

            // its private marshaller and context object attrbutes)

            // FALL THROUGH... will throw an exception

        } else if (StreamSource.class.isAssignableFrom(sourceClass)) {

            return createStreamSource(sourceClass);

        } else if ((sourceClass == null)

                   || DOMSource.class.isAssignableFrom(sourceClass)) {

            return createDOMSource(sourceClass);

        } else if (SAXSource.class.isAssignableFrom(sourceClass)) {

            return createSAXSource(sourceClass);

        } else if (StAXSource.class.isAssignableFrom(sourceClass)) {

            return createStAXSource(sourceClass);

        }



        throw Util.invalidArgument("sourceClass: " + sourceClass);

    }



    /**

     * Retrieves a new StreamSource for reading the XML value designated by
this

     * SQLXML instance. <p>

     *

     * @param sourceClass The class of the source

     * @throws java.sql.SQLException if there is an error processing the XML

     *      value or if the given <tt>sourceClass</tt> is not supported.

     * @return a new StreamSource for reading the XML value designated by
this

     *      SQLXML instance

     */

    @SuppressWarnings("unchecked")

    protected <T extends Source>T createStreamSource(

            Class<T> sourceClass) throws SQLException {



        StreamSource source = null;



        try {

            source = (sourceClass == null) ? new StreamSource()

                    : (StreamSource) sourceClass.newInstance();

        } catch (SecurityException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (InstantiationException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (IllegalAccessException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (ClassCastException ex) {

            throw Exceptions.sourceInstantiation(ex);

        }



        Reader reader = getCharacterStreamImpl();



        source.setReader(reader);



        return (T) source;

    }



    /**

     * Retrieves a new DOMSource for reading the XML value designated by
this

     * SQLXML instance. <p>

     *

     * @param sourceClass The class of the source

     * @throws java.sql.SQLException if there is an error processing the XML

     *      value or if the given <tt>sourceClass</tt> is not supported.

     * @return a new DOMSource for reading the XML value designated by this

     *      SQLXML instance

     */

    @SuppressWarnings("unchecked")

    protected <T extends Source>T createDOMSource(

            Class<T> sourceClass) throws SQLException {



        DOMSource source = null;



        try {

            source = (sourceClass == null) ? new DOMSource()

                    : (DOMSource) sourceClass.newInstance();

        } catch (SecurityException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (IllegalAccessException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (InstantiationException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (ClassCastException ex) {

            throw Exceptions.sourceInstantiation(ex);

        }



        Transformer  transformer  = JDBCSQLXML.getIdentityTransformer();

        InputStream  inputStream  = this.getBinaryStreamImpl();

        StreamSource streamSource = new StreamSource();

        DOMResult    domResult    = new DOMResult();



        streamSource.setInputStream(inputStream);



        try {

            transformer.transform(streamSource, domResult);

        } catch (TransformerException ex) {

            throw Exceptions.transformFailed(ex);

        }

        source.setNode(domResult.getNode());



        return (T) source;

    }



    /**

     * Retrieves a new SAXSource for reading the XML value designated by
this

     * SQLXML instance. <p>

     *

     * @param sourceClass The class of the source

     * @throws java.sql.SQLException if there is an error processing the XML

     *      value or if the given <tt>sourceClass</tt> is not supported.

     * @return a new SAXSource for reading the XML value designated by this

     *      SQLXML instance

     */

    @SuppressWarnings("unchecked")

    protected <T extends Source>T createSAXSource(

            Class<T> sourceClass) throws SQLException {



        SAXSource source = null;



        try {

            source = (sourceClass == null) ? new SAXSource()

                    : (SAXSource) sourceClass.newInstance();

        } catch (SecurityException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (InstantiationException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (IllegalAccessException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (ClassCastException ex) {

            throw Exceptions.sourceInstantiation(ex);

        }



        Reader      reader      = getCharacterStreamImpl();

        InputSource inputSource = new InputSource(reader);



        source.setInputSource(inputSource);



        return (T) source;

    }



    /**

     * Retrieves a new StAXSource for reading the XML value designated by
this

     * SQLXML instance. <p>

     *

     * @param sourceClass The class of the source

     * @throws java.sql.SQLException if there is an error processing the XML

     *      value or if the given <tt>sourceClass</tt> is not supported.

     * @return a new StAXSource for reading the XML value designated by this

     *      SQLXML instance

     */

    @SuppressWarnings("unchecked")

    protected <T extends Source>T createStAXSource(

            Class<T> sourceClass) throws SQLException {



        StAXSource      source      = null;

        Constructor     sourceCtor  = null;

        Reader          reader      = null;

        XMLInputFactory factory     = null;

        XMLEventReader  eventReader = null;



        try {

            factory = XMLInputFactory.newInstance();

        } catch (FactoryConfigurationError ex) {

            throw Exceptions.sourceInstantiation(ex);

        }



        try {

            sourceCtor =

                (sourceClass == null)

                ? StAXSource.class.getConstructor(XMLEventReader.class)

                : sourceClass.getConstructor(XMLEventReader.class);

        } catch (SecurityException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (NoSuchMethodException ex) {

            throw Exceptions.sourceInstantiation(ex);

        }

        reader = getCharacterStreamImpl();



        try {

            eventReader = factory.createXMLEventReader(reader);

        } catch (XMLStreamException ex) {

            throw Exceptions.sourceInstantiation(ex);

        }



        try {

            source = (StAXSource) sourceCtor.newInstance(eventReader);

        } catch (SecurityException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (IllegalArgumentException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (IllegalAccessException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (InstantiationException ex) {

            throw Exceptions.sourceInstantiation(ex);

        } catch (InvocationTargetException ex) {

            throw Exceptions.sourceInstantiation(ex.getTargetException());

        } catch (ClassCastException ex) {

            throw Exceptions.sourceInstantiation(ex);

        }



        return (T) source;

    }



    /**

     * Retrieves a new Result for setting the XML value designated by this

     * SQLXML instance.

     *

     * @param resultClass The class of the result, or null.

     * @throws java.sql.SQLException if there is an error processing the XML

     *         value or the state is not writable

     * @return for setting the XML value designated by this SQLXML instance.

     */

    protected <T extends Result>T createResult(

            Class<T> resultClass) throws SQLException {



        checkWritable();

        setWritable(false);

        setReadable(true);



        if (JAXBResult.class.isAssignableFrom(resultClass)) {



            // Must go first presently, since JAXBResult extends SAXResult

            // (purely as an implmentation detail) and it's not possible

            // to instantiate a valid JAXBResult with a Zero-Args

            // constructor(or any subclass thereof, due to the finality of

            // its private UnmarshallerHandler)

            // FALL THROUGH... will throw an exception

        } else if ((resultClass == null)

                   || StreamResult.class.isAssignableFrom(resultClass)) {

            return createStreamResult(resultClass);

        } else if (DOMResult.class.isAssignableFrom(resultClass)) {

            return createDOMResult(resultClass);

        } else if (SAXResult.class.isAssignableFrom(resultClass)) {

            return createSAXResult(resultClass);

        } else if (StAXResult.class.isAssignableFrom(resultClass)) {

            return createStAXResult(resultClass);

        }



        throw Util.invalidArgument("resultClass: " + resultClass);

    }



    /**

     * Retrieves a new StreamResult for setting the XML value designated by
this

     * SQLXML instance.

     *

     * @param resultClass The class of the result, or null.

     * @throws java.sql.SQLException if there is an error processing the XML

     *         value

     * @return for setting the XML value designated by this SQLXML instance.

     */



//  @SuppressWarnings("unchecked")

    protected <T extends Result>T createStreamResult(

            Class<T> resultClass) throws SQLException {



        StreamResult result = null;



        try {

            result = (resultClass == null) ? new StreamResult()

                    : (StreamResult) resultClass.newInstance();

        } catch (SecurityException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (InstantiationException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (IllegalAccessException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (ClassCastException ex) {

            throw Exceptions.resultInstantiation(ex);

        }



        OutputStream outputStream = setBinaryStreamImpl();



        result.setOutputStream(outputStream);



        return (T) result;

    }



    /**

     * Retrieves a new DOMResult for setting the XML value designated by
this

     * SQLXML instance.

     *

     * @param resultClass The class of the result, or null.

     * @throws java.sql.SQLException if there is an error processing the XML

     *         value

     * @return for setting the XML value designated by this SQLXML instance.

     */

    @SuppressWarnings("unchecked")

    protected <T extends Result>T createDOMResult(

            Class<T> resultClass) throws SQLException {



        try {

            return (resultClass == null) ? ((T) new DOMResult())

                    : resultClass.newInstance();

        } catch (SecurityException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (InstantiationException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (IllegalAccessException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (ClassCastException ex) {

            throw Exceptions.resultInstantiation(ex);

        }

    }



    /**

     *  Retrieves a new SAXResult for setting the XML value designated by
this

     *  SQLXML instance.

     *

     *  @param resultClass The class of the result, or null.

     *  @throws java.sql.SQLException if there is an error processing the
XML

     *          value

     *  @return for setting the XML value designated by this SQLXML
instance.

     */

    @SuppressWarnings("unchecked")

    protected <T extends Result>T createSAXResult(

            Class<T> resultClass) throws SQLException {



        SAXResult result = null;



        try {

            result = (resultClass == null) ? new SAXResult()

                    : (SAXResult) resultClass.newInstance();

        } catch (SecurityException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (InstantiationException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (IllegalAccessException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (ClassCastException ex) {

            throw Exceptions.resultInstantiation(ex);

        }



        StAXResult          staxResult = createStAXResult(null);

        XMLStreamWriter     xmlWriter  = staxResult.getXMLStreamWriter();

        SAX2XMLStreamWriter handler    = new SAX2XMLStreamWriter(xmlWriter);



        result.setHandler(handler);



        return (T) result;

    }



    /**

     *  Retrieves a new DOMResult for setting the XML value designated by
this

     *  SQLXML instance.

     *

     *  @param resultClass The class of the result, or null.

     *  @throws java.sql.SQLException if there is an error processing the
XML

     *          value

     *  @return for setting the XML value designated by this SQLXML
instance.

     */

    @SuppressWarnings("unchecked")

    protected <T extends Result>T createStAXResult(

            Class<T> resultClass) throws SQLException {



        StAXResult       result       = null;

        OutputStream     outputStream = this.setBinaryStreamImpl();

        Constructor      ctor;

        XMLOutputFactory factory;

        XMLStreamWriter  xmlStreamWriter;



        try {

            factory         = XMLOutputFactory.newInstance();

            xmlStreamWriter = factory.createXMLStreamWriter(outputStream);



            if (resultClass == null) {

                result = new StAXResult(xmlStreamWriter);

            } else {

                ctor   = resultClass.getConstructor(XMLStreamWriter.class);

                result = (StAXResult) ctor.newInstance(xmlStreamWriter);

            }

        } catch (SecurityException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (IllegalArgumentException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (IllegalAccessException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (InvocationTargetException ex) {

            throw Exceptions.resultInstantiation(ex.getTargetException());

        } catch (FactoryConfigurationError ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (InstantiationException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (NoSuchMethodException ex) {

            throw Exceptions.resultInstantiation(ex);

        } catch (XMLStreamException ex) {

            throw Exceptions.resultInstantiation(ex);

        }



        return (T) result;

    }



    /**

     * Basically just a namespace to isolate SQLXML exception generation

     */

    protected static class Exceptions {



        /**

         * Construction Disabled.

         */

        private Exceptions() {

        }



        /**

         *  Retrieves a new SQLXML DOM instantiation exception.

         *

         * @param cause of the exception

         */

        static SQLException domInstantiation(Throwable cause) {



            SQLException ex = Util.sqlException(ErrorCode.GENERAL_ERROR,

                "SQLXML DOM instantiation failed: " + cause);



            ex.initCause(cause);



            return ex;

        }



        /**

         * Retrieves a new SQLXML source instantiation exception.

         *

         * @param cause of the exception.

         * @return a new SQLXML source instantiation exception

         */

        static SQLException sourceInstantiation(Throwable cause) {



            SQLException ex = Util.sqlException(ErrorCode.GENERAL_ERROR,

                "SQLXML Source instantiation failed: " + cause);



            ex.initCause(cause);



            return ex;

        }



        /**

         * Retrieves a new SQLXML result instantiation exception.

         *

         * @param cause of the exception.

         * @return a new SQLXML result instantiation exception

         */

        static SQLException resultInstantiation(Throwable cause) {



            SQLException ex = Util.sqlException(ErrorCode.GENERAL_ERROR,

                "SQLXML Result instantiation failed: " + cause);



            ex.initCause(cause);



            return ex;

        }



        /**

         * Retrieves a new SQLXML parse failed exception.

         *

         * @param cause of the exception.

         * @return a new SQLXML parse failed exception

         */

        static SQLException parseFailed(Throwable cause) {



            SQLException ex = Util.sqlException(ErrorCode.GENERAL_IO_ERROR,

                "parse failed: " + cause);



            ex.initCause(cause);



            return ex;

        }



        /**

         * Retrieves a new SQLXML transform failed exception.

         *

         * @param cause of the exception.

         * @return a new SQLXML parse failed exception

         */

        static SQLException transformFailed(Throwable cause) {



            SQLException ex = Util.sqlException(ErrorCode.GENERAL_IO_ERROR,

                "transform failed: " + cause);



            ex.initCause(cause);



            return ex;

        }



        /**

         * Retrieves a new SQLXML not readable exception.

         *

         * @return a new SQLXML not readable exception

         */

        static SQLException notReadable() {

            return Util.sqlException(ErrorCode.GENERAL_IO_ERROR,

                                     "SQLXML in not readable state");

        }



        /**

         * Retrieves a new SQLXML not writable exception.

         *

         * @return a new SQLXML not writable exception

         */

        static SQLException notWritable() {

            return Util.sqlException(ErrorCode.GENERAL_IO_ERROR,

                                     "SQLXML in not writable state");

        }



        /**

         * Currently unused.

         *

         * @return never

         */

        static SQLException directUpdateByLocatorNotSupported() {

            return Util.sqlException(ErrorCode.X_0A000,

                                     "SQLXML direct update by locator");

        }



        /**

         * Retrieves a new SQLXML in freed state exception.

         *

         * @return a new SQLXML in freed state exception

         */

        static SQLException inFreedState() {

            return Util.sqlException(ErrorCode.GENERAL_ERROR,

                                     "SQLXML in freed state");

        }

    }



    //
-------------------------------------------------------------------------



    /**

     * Builds a DOM from SAX events.

     */

    protected static class SAX2DOMBuilder implements ContentHandler,

            Closeable {



        /**

         *

         */

        private boolean closed;



        /**

         *

         */

        private Element currentElement;



        // --------------------- internal implementation
-----------------------



        /**

         *

         */

        private Node currentNode;



        /**

         *

         */

        private Document document;



        /**

         *

         */

        private Locator locator;



        /**

         * <p>Creates a new instance of SAX2DOMBuilder, which creates

         * a new document. The document is available via

         * {@link #getDocument()}.</p>

         * @throws javax.xml.parsers.ParserConfigurationException

         */

        public SAX2DOMBuilder() throws ParserConfigurationException {



            DocumentBuilderFactory documentBuilderFactory;

            DocumentBuilder        documentBuilder;



            documentBuilderFactory = DocumentBuilderFactory.newInstance();



            documentBuilderFactory.setValidating(false);

            documentBuilderFactory.setNamespaceAware(true);



            documentBuilder  = documentBuilderFactory.newDocumentBuilder();

            this.document    = documentBuilder.newDocument();

            this.currentNode = this.document;

        }



        /**

         * Receive an object for locating the origin of SAX document events.

         *

         * <p>SAX parsers are strongly encouraged (though not absolutely

         * required) to supply a locator: if it does so, it must supply

         * the locator to the application by invoking this method before

         * invoking any of the other methods in the ContentHandler

         * interface.</p>

         *

         * <p>The locator allows the application to determine the end

         * position of any document-related event, even if the parser is

         * not reporting an error.  Typically, the application will

         * use this information for reporting its own errors (such as

         * character content that does not match an application's

         * business rules).  The information returned by the locator

         * is probably not sufficient for use with a search engine.</p>

         *

         * <p>Note that the locator will return correct information only

         * during the invocation SAX event callbacks after

         * {@link #startDocument startDocument} returns and before

         * {@link #endDocument endDocument} is called.  The

         * application should not attempt to use it at any other time.</p>

         *

         * @param locator an object that can return the location of

         *                any SAX document event

         * @see org.xml.sax.Locator

         */

        public void setDocumentLocator(Locator locator) {

            this.locator = locator;

        }



        /**

         * Retrieves the Locator. <p>

         * @return the Locator

         */

        public Locator getDocumentLocator() {

            return this.locator;

        }



        /**

         * Receive notification of the beginning of a document.

         *

         * <p>The SAX parser will invoke this method only once, before any

         * other event callbacks (except for {@link #setDocumentLocator

         * setDocumentLocator}).</p>

         *

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #endDocument

         */

        public void startDocument() throws SAXException {

            checkClosed();

        }



        /**

         * Receive notification of the end of a document.

         *

         * <p><strong>There is an apparent contradiction between the

         * documentation for this method and the documentation for {@link

         * org.xml.sax.ErrorHandler#fatalError}.  Until this ambiguity is

         * resolved in a future major release, clients should make no

         * assumptions about whether endDocument() will or will not be

         * invoked when the parser has reported a fatalError() or thrown

         * an exception.</strong></p>

         *

         * <p>The SAX parser will invoke this method only once, and it will

         * be the last method invoked during the parse.  The parser shall

         * not invoke this method until it has either abandoned parsing

         * (because of an unrecoverable error) or reached the end of

         * input.</p>

         *

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #startDocument

         */

        public void endDocument() throws SAXException {

            checkClosed();

        }



        /**

         * Begin the scope of a prefix-URI Namespace mapping.

         *

         * <p>The information from this event is not necessary for

         * normal Namespace processing: the SAX XML reader will

         * automatically replace prefixes for element and attribute

         * names when the <code>http://xml.org/sax/features/namespaces
</code>

         * feature is <var>true</var> (the default).</p>

         *

         * <p>There are cases, however, when applications need to

         * use prefixes in character data or in attribute values,

         * where they cannot safely be expanded automatically; the

         * start/endPrefixMapping event supplies the information

         * to the application to expand prefixes in those contexts

         * itself, if necessary.</p>

         *

         * <p>Note that start/endPrefixMapping events are not

         * guaranteed to be properly nested relative to each other:

         * all startPrefixMapping events will occur immediately before the

         * corresponding {@link #startElement startElement} event,

         * and all {@link #endPrefixMapping endPrefixMapping}

         * events will occur immediately after the corresponding

         * {@link #endElement endElement} event,

         * but their order is not otherwise

         * guaranteed.</p>

         *

         * <p>There should never be start/endPrefixMapping events for the

         * "xml" prefix, since it is predeclared and immutable.</p>

         *

         * @param prefix the Namespace prefix being declared.

         *      An empty string is used for the default element namespace,

         *      which has no prefix.

         * @param uri the Namespace URI the prefix is mapped to

         * @throws org.xml.sax.SAXException the client may throw

         *            an exception during processing

         * @see #endPrefixMapping

         * @see #startElement

         */

        public void startPrefixMapping(String prefix,

                                       String uri) throws SAXException {

            checkClosed();

        }



        /**

         * End the scope of a prefix-URI mapping.

         *

         * <p>See {@link #startPrefixMapping startPrefixMapping} for

         * details.  These events will always occur immediately after the

         * corresponding {@link #endElement endElement} event, but the order
of

         * {@link #endPrefixMapping endPrefixMapping} events is not
otherwise

         * guaranteed.</p>

         *

         * @param prefix the prefix that was being mapped.

         *      This is the empty string when a default mapping scope ends.

         * @throws org.xml.sax.SAXException the client may throw

         *            an exception during processing

         * @see #startPrefixMapping

         * @see #endElement

         */

        public void endPrefixMapping(String prefix) throws SAXException {

            checkClosed();

        }



        /**

         * Receive notification of the beginning of an element.

         *

         * <p>The Parser will invoke this method at the beginning of every

         * element in the XML document; there will be a corresponding

         * {@link #endElement endElement} event for every startElement event

         * (even when the element is empty). All of the element's content
will be

         * reported, in order, before the corresponding endElement

         * event.</p>

         *

         * <p>This event allows up to three name components for each

         * element:</p>

         *

         * <ol>

         * <li>the Namespace URI;</li>

         * <li>the local name; and</li>

         * <li>the qualified (prefixed) name.</li>

         * </ol>

         *

         * <p>Any or all of these may be provided, depending on the

         * values of the <var>http://xml.org/sax/features/namespaces</var>

         * and the <var>http://xml.org/sax/features/namespace-prefixes</var>

         * properties:</p>

         *

         * <ul>

         * <li>the Namespace URI and local name are required when

         * the namespaces property is <var>true</var> (the default), and are

         * optional when the namespaces property is <var>false</var> (if one
is

         * specified, both must be);</li>

         * <li>the qualified name is required when the namespace-prefixes
property

         * is <var>true</var>, and is optional when the namespace-prefixes
property

         * is <var>false</var> (the default).</li>

         * </ul>

         *

         * <p>Note that the attribute list provided will contain only

         * attributes with explicit values (specified or defaulted):

         * #IMPLIED attributes will be omitted.  The attribute list

         * will contain attributes used for Namespace declarations

         * (xmlns* attributes) only if the

         * <code>http://xml.org/sax/features/namespace-prefixes</code>

         * property is true (it is false by default, and support for a

         * true value is optional).</p>

         *

         * <p>Like {@link #characters characters()}, attribute values may
have

         * characters that need more than one <code>char</code> value.  </p>

         *

         * @param uri the Namespace URI, or the empty string if the

         *        element has no Namespace URI or if Namespace

         *        processing is not being performed

         * @param localName the local name (without prefix), or the

         *        empty string if Namespace processing is not being

         *        performed

         * @param qName the qualified name (with prefix), or the

         *        empty string if qualified names are not available

         * @param atts the attributes attached to the element.  If

         *        there are no attributes, it shall be an empty

         *        Attributes object.  The value of this object after

         *        startElement returns is undefined

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #endElement

         * @see org.xml.sax.Attributes

         * @see org.xml.sax.helpers.AttributesImpl

         */

        public void startElement(String uri, String localName, String qName,

                                 Attributes atts) throws SAXException {



            checkClosed();



            Element element;



            if ((uri == null) || (uri.length() == 0)) {

                element = getDocument().createElement(qName);

            } else {

                element = getDocument().createElementNS(uri, qName);

            }



            if (atts != null) {

                for (int i = 0; i < atts.getLength(); i++) {

                    String attrURI   = atts.getURI(i);

                    String attrQName = atts.getQName(i);

                    String attrValue = atts.getValue(i);



                    if ((attrURI == null) || (attrURI.length() == 0)) {

                        element.setAttribute(attrQName, attrValue);

                    } else {

                        element.setAttributeNS(attrURI, attrQName,
attrValue);

                    }

                }

            }

            getCurrentNode().appendChild(element);

            setCurrentNode(element);



            if (getCurrentElement() == null) {

                setCurrentElement(element);

            }

        }



        /**

         * Receive notification of the end of an element.

         *

         * <p>The SAX parser will invoke this method at the end of every

         * element in the XML document; there will be a corresponding

         * {@link #startElement startElement} event for every endElement

         * event (even when the element is empty).</p>

         *

         * <p>For information on the names, see startElement.</p>

         *

         * @param uri the Namespace URI, or the empty string if the

         *        element has no Namespace URI or if Namespace

         *        processing is not being performed

         * @param localName the local name (without prefix), or the

         *        empty string if Namespace processing is not being

         *        performed

         * @param qName the qualified XML name (with prefix), or the

         *        empty string if qualified names are not available

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         */

        public void endElement(String uri, String localName,

                               String qName) throws SAXException {

            checkClosed();

            setCurrentNode(getCurrentNode().getParentNode());

        }



        /**

         * Receive notification of character data.

         *

         * <p>The Parser will call this method to report each chunk of

         * character data.  SAX parsers may return all contiguous character

         * data in a single chunk, or they may split it into several

         * chunks; however, all of the characters in any single event

         * must come from the same external entity so that the Locator

         * provides useful information.</p>

         *

         * <p>The application must not attempt to read from the array

         * outside of the specified range.</p>

         *

         * <p>Individual characters may consist of more than one Java

         * <code>char</code> value.  There are two important cases where
this

         * happens, because characters can't be represented in just sixteen
bits.

         * In one case, characters are represented in a <em>Surrogate
Pair</em>,

         * using two special Unicode values. Such characters are in the
so-called

         * "Astral Planes", with a code point above U+FFFF.  A second case
involves

         * composite characters, such as a base character combining with one
or

         * more accent characters. </p>

         *

         * <p> Your code should not assume that algorithms using

         * <code>char</code>-at-a-time idioms will be working in character

         * units; in some cases they will split characters.  This is
relevant

         * wherever XML permits arbitrary characters, such as attribute
values,

         * processing instruction data, and comments as well as in data
reported

         * from this method.  It's also generally relevant whenever Java
code

         * manipulates internationalized text; the issue isn't unique to
XML.</p>

         *

         * <p>Note that some parsers will report whitespace in element

         * content using the {@link #ignorableWhitespace
ignorableWhitespace}

         * method rather than this one (validating parsers <em>must</em>

         * do so).</p>

         *

         * @param ch the characters from the XML document

         * @param start the start position in the array

         * @param length the number of characters to read from the array

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #ignorableWhitespace

         * @see org.xml.sax.Locator

         */

        public void characters(char[] ch, int start,

                               int length) throws SAXException {



            checkClosed();



            Node   node = getCurrentNode().getLastChild();

            String s    = new String(ch, start, length);



            if ((node != null) && (node.getNodeType() == Node.TEXT_NODE)) {

                ((Text) node).appendData(s);

            } else {

                Text text = getDocument().createTextNode(s);



                getCurrentNode().appendChild(text);

            }

        }



        /**

         * Receive notification of ignorable whitespace in element content.

         *

         * <p>Validating Parsers must use this method to report each chunk

         * of whitespace in element content (see the W3C XML 1.0

         * recommendation, section 2.10): non-validating parsers may also

         * use this method if they are capable of parsing and using

         * content models.</p>

         *

         * <p>SAX parsers may return all contiguous whitespace in a single

         * chunk, or they may split it into several chunks; however, all of

         * the characters in any single event must come from the same

         * external entity, so that the Locator provides useful

         * information.</p>

         *

         * <p>The application must not attempt to read from the array

         * outside of the specified range.</p>

         *

         * @param ch the characters from the XML document

         * @param start the start position in the array

         * @param length the number of characters to read from the array

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #characters

         */

        public void ignorableWhitespace(char[] ch, int start,

                                        int length) throws SAXException {

            characters(ch, start, length);

        }



        /**

         * Receive notification of a processing instruction.

         *

         * <p>The Parser will invoke this method once for each processing

         * instruction found: note that processing instructions may occur

         * before or after the main document element.</p>

         *

         * <p>A SAX parser must never report an XML declaration (XML 1.0,

         * section 2.8) or a text declaration (XML 1.0, section 4.3.1)

         * using this method.</p>

         *

         * <p>Like {@link #characters characters()}, processing instruction

         * data may have characters that need more than one
<code>char</code>

         * value. </p>

         *

         * @param target the processing instruction target

         * @param data the processing instruction data, or null if

         *        none was supplied.  The data does not include any

         *        whitespace separating it from the target

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         */

        public void processingInstruction(String target,

                String data) throws SAXException {



            checkClosed();



            ProcessingInstruction processingInstruction;



            processingInstruction =

                getDocument().createProcessingInstruction(target, data);



            getCurrentNode().appendChild(processingInstruction);

        }



        /**

         * Receive notification of a skipped entity.

         * This is not called for entity references within markup constructs

         * such as element start tags or markup declarations.  (The XML

         * recommendation requires reporting skipped external entities.

         * SAX also reports internal entity expansion/non-expansion, except

         * within markup constructs.)

         *

         * <p>The Parser will invoke this method each time the entity is

         * skipped.  Non-validating processors may skip entities if they

         * have not seen the declarations (because, for example, the

         * entity was declared in an external DTD subset).  All processors

         * may skip external entities, depending on the values of the

         * <code>http://xml.org/sax/features/external-general-entities
</code>

         * and the

         * <code>http://xml.org/sax/features/external-parameter-entities
</code>

         * properties.</p>

         *

         * @param name the name of the skipped entity.  If it is a

         *        parameter entity, the name will begin with '%', and if

         *        it is the external DTD subset, it will be the string

         *        "[dtd]"

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         */

        public void skippedEntity(String name) throws SAXException {



            checkClosed();



            EntityReference entityReference =

                getDocument().createEntityReference(name);



            getCurrentNode().appendChild(entityReference);

        }



        /**

         * Closes this DOMBuilder.

         */

        public void close() {



            this.closed         = true;

            this.document       = null;

            this.currentElement = null;

            this.currentNode    = null;

            this.locator        = null;

        }



        /**

         * Retrieves whether this DOMBuilder is closed.

         */

        public boolean isClosed() {

            return this.closed;

        }



        /**

         * Checks whether this DOMBuilder is closed.

         *

         * @throws SAXException if this DOMBuilder is closed.

         */

        protected void checkClosed() throws SAXException {



            if (isClosed()) {

                throw new SAXException("content handler is closed.");    //
NOI18N

            }

        }



        /**

         * Retrieves the document. <p>

         */

        protected Document getDocument() {

            return this.document;

        }



        /**

         * Retreives the current element. <p>

         */

        protected Element getCurrentElement() {

            return this.currentElement;

        }



        /**

         * Assigns the current element.

         * @param element

         */

        protected void setCurrentElement(Element element) {

            this.currentElement = element;

        }



        /**

         * Retrieves the current node. <p>

         */

        protected Node getCurrentNode() {

            return this.currentNode;

        }



        /**

         * Assigns the current node. <p>

         * @param node

         */

        protected void setCurrentNode(Node node) {

            this.currentNode = node;

        }

    }



    /**

     * Writes to a {@link javax.xml.stream.XMLStreamWriter XMLStreamWriter}

     * from SAX events.

     */

    public static class SAX2XMLStreamWriter implements ContentHandler,

            Closeable {



        /**

         * Namespace declarations for an upcoming element.

         */

        private List<QualifiedName> namespaces =

            new ArrayList<QualifiedName>();



        /**

         * Whether this object is closed.

         */

        private boolean closed;



        /**

         * This object's SAX locator.

         */

        private Locator locator;



        /**

         * XML stream writer where events are pushed.

         */

        private XMLStreamWriter writer;



        /**

         * Constructs a new SAX2XMLStreamWriter that writes SAX events to
the

         * designated XMLStreamWriter.

         *

         * @param writer the writer to which to write SAX events

         */

        public SAX2XMLStreamWriter(XMLStreamWriter writer) {



            if (writer == null) {

                throw new NullPointerException("writer");

            }

            this.writer = writer;

        }



        /**

         * Receive notification of the beginning of a document.

         *

         * <p>The SAX parser will invoke this method only once, before any

         * other event callbacks (except for {@link #setDocumentLocator

         * setDocumentLocator}).</p>

         *

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #endDocument

         */

        public void startDocument() throws SAXException {



            checkClosed();



            try {

                this.writer.writeStartDocument();

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }

        }



        /**

         * Receive notification of the end of a document.

         *

         * <p><strong>There is an apparent contradiction between the

         * documentation for this method and the documentation for {@link

         * org.xml.sax.ErrorHandler#fatalError}.  Until this ambiguity is

         * resolved in a future major release, clients should make no

         * assumptions about whether endDocument() will or will not be

         * invoked when the parser has reported a fatalError() or thrown

         * an exception.</strong></p>

         *

         * <p>The SAX parser will invoke this method only once, and it will

         * be the last method invoked during the parse.  The parser shall

         * not invoke this method until it has either abandoned parsing

         * (because of an unrecoverable error) or reached the end of

         * input.</p>

         *

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #startDocument

         */

        public void endDocument() throws SAXException {



            checkClosed();



            try {

                this.writer.writeEndDocument();

                this.writer.flush();

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }

        }



        /**

         * Receive notification of character data.

         *

         * <p>The Parser will call this method to report each chunk of

         * character data.  SAX parsers may return all contiguous character

         * data in a single chunk, or they may split it into several

         * chunks; however, all of the characters in any single event

         * must come from the same external entity so that the Locator

         * provides useful information.</p>

         *

         * <p>The application must not attempt to read from the array

         * outside of the specified range.</p>

         *

         * <p>Individual characters may consist of more than one Java

         * <code>char</code> value.  There are two important cases where
this

         * happens, because characters can't be represented in just sixteen
bits.

         * In one case, characters are represented in a <em>Surrogate
Pair</em>,

         * using two special Unicode values. Such characters are in the
so-called

         * "Astral Planes", with a code point above U+FFFF.  A second case
involves

         * composite characters, such as a base character combining with one
or

         * more accent characters. </p>

         *

         * <p> Your code should not assume that algorithms using

         * <code>char</code>-at-a-time idioms will be working in character

         * units; in some cases they will split characters.  This is
relevant

         * wherever XML permits arbitrary characters, such as attribute
values,

         * processing instruction data, and comments as well as in data
reported

         * from this method.  It's also generally relevant whenever Java
code

         * manipulates internationalized text; the issue isn't unique to
XML.</p>

         *

         * <p>Note that some parsers will report whitespace in element

         * content using the {@link #ignorableWhitespace
ignorableWhitespace}

         * method rather than this one (validating parsers <em>must</em>

         * do so).</p>

         *

         * @param ch the characters from the XML document

         * @param start the start position in the array

         * @param length the number of characters to read from the array

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #ignorableWhitespace

         * @see org.xml.sax.Locator

         */

        public void characters(char[] ch, int start,

                               int length) throws SAXException {



            checkClosed();



            try {

                this.writer.writeCharacters(ch, start, length);

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }

        }



        /**

         * Receive notification of the beginning of an element.

         *

         * <p>The Parser will invoke this method at the beginning of every

         * element in the XML document; there will be a corresponding

         * {@link #endElement endElement} event for every startElement event

         * (even when the element is empty). All of the element's content
will be

         * reported, in order, before the corresponding endElement

         * event.</p>

         *

         * <p>This event allows up to three name components for each

         * element:</p>

         *

         * <ol>

         * <li>the Namespace URI;</li>

         * <li>the local name; and</li>

         * <li>the qualified (prefixed) name.</li>

         * </ol>

         *

         * <p>Any or all of these may be provided, depending on the

         * values of the <var>http://xml.org/sax/features/namespaces</var>

         * and the <var>http://xml.org/sax/features/namespace-prefixes</var>

         * properties:</p>

         *

         * <ul>

         * <li>the Namespace URI and local name are required when

         * the namespaces property is <var>true</var> (the default), and are

         * optional when the namespaces property is <var>false</var> (if one
is

         * specified, both must be);</li>

         * <li>the qualified name is required when the namespace-prefixes
property

         * is <var>true</var>, and is optional when the namespace-prefixes
property

         * is <var>false</var> (the default).</li>

         * </ul>

         *

         * <p>Note that the attribute list provided will contain only

         * attributes with explicit values (specified or defaulted):

         * #IMPLIED attributes will be omitted.  The attribute list

         * will contain attributes used for Namespace declarations

         * (xmlns* attributes) only if the

         * <code>http://xml.org/sax/features/namespace-prefixes</code>

         * property is true (it is false by default, and support for a

         * true value is optional).</p>

         *

         * <p>Like {@link #characters characters()}, attribute values may
have

         * characters that need more than one <code>char</code> value.  </p>

         *

         * @param namespaceURI the Namespace URI, or the empty string if the

         *        element has no Namespace URI or if Namespace

         *        processing is not being performed

         * @param localName the local name (without prefix), or the

         *        empty string if Namespace processing is not being

         *        performed

         * @param qName the qualified name (with prefix), or the

         *        empty string if qualified names are not available

         * @param atts the attributes attached to the element.  If

         *        there are no attributes, it shall be an empty

         *        Attributes object.  The value of this object after

         *        startElement returns is undefined

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #endElement

         * @see org.xml.sax.Attributes

         * @see org.xml.sax.helpers.AttributesImpl

         */

        public void startElement(String namespaceURI, String localName,

                                 String qName,

                                 Attributes atts) throws SAXException {



            checkClosed();



            try {

                int    qi     = qName.indexOf(':');

                String prefix = (qi > 0) ? qName.substring(0, qi)

                        : "";



                this.writer.writeStartElement(prefix, localName,
namespaceURI);



                int length = namespaces.size();



                for (int i = 0; i < length; i++) {

                    QualifiedName ns = namespaces.get(i);



                    this.writer.writeNamespace(ns.prefix, ns.namespaceName);

                }

                namespaces.clear();



                length = atts.getLength();



                for (int i = 0; i < length; i++) {

                    this.writer.writeAttribute(atts.getURI(i),

                            atts.getLocalName(i), atts.getValue(i));

                }

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }

        }



        /**

         * Receive notification of the end of an element.

         *

         * <p>The SAX parser will invoke this method at the end of every

         * element in the XML document; there will be a corresponding

         * {@link #startElement startElement} event for every endElement

         * event (even when the element is empty).</p>

         *

         * <p>For information on the names, see startElement.</p>

         *

         * @param namespaceURI the Namespace URI, or the empty string if the

         *        element has no Namespace URI or if Namespace

         *        processing is not being performed

         * @param localName the local name (without prefix), or the

         *        empty string if Namespace processing is not being

         *        performed

         * @param qName the qualified XML name (with prefix), or the

         *        empty string if qualified names are not available

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         */

        public void endElement(String namespaceURI, String localName,

                               String qName) throws SAXException {



            checkClosed();



            try {

                this.writer.writeEndElement();

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }

        }



        /**

         * Begin the scope of a prefix-URI Namespace mapping.

         *

         * <p>The information from this event is not necessary for

         * normal Namespace processing: the SAX XML reader will

         * automatically replace prefixes for element and attribute

         * names when the <code>http://xml.org/sax/features/namespaces
</code>

         * feature is <var>true</var> (the default).</p>

         *

         * <p>There are cases, however, when applications need to

         * use prefixes in character data or in attribute values,

         * where they cannot safely be expanded automatically; the

         * start/endPrefixMapping event supplies the information

         * to the application to expand prefixes in those contexts

         * itself, if necessary.</p>

         *

         * <p>Note that start/endPrefixMapping events are not

         * guaranteed to be properly nested relative to each other:

         * all startPrefixMapping events will occur immediately before the

         * corresponding {@link #startElement startElement} event,

         * and all {@link #endPrefixMapping endPrefixMapping}

         * events will occur immediately after the corresponding

         * {@link #endElement endElement} event,

         * but their order is not otherwise

         * guaranteed.</p>

         *

         * <p>There should never be start/endPrefixMapping events for the

         * "xml" prefix, since it is predeclared and immutable.</p>

         *

         * @param prefix the Namespace prefix being declared.

         *      An empty string is used for the default element namespace,

         *      which has no prefix.

         * @param uri the Namespace URI the prefix is mapped to

         * @throws org.xml.sax.SAXException the client may throw

         *            an exception during processing

         * @see #endPrefixMapping

         * @see #startElement

         */

        public void startPrefixMapping(String prefix,

                                       String uri) throws SAXException {



            checkClosed();



            try {

                this.writer.setPrefix(prefix, uri);

                namespaces.add(new QualifiedName(prefix, uri));

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }

        }



        /**

         * End the scope of a prefix-URI mapping.

         *

         * <p>See {@link #startPrefixMapping startPrefixMapping} for

         * details.  These events will always occur immediately after the

         * corresponding {@link #endElement endElement} event, but the order
of

         * {@link #endPrefixMapping endPrefixMapping} events is not
otherwise

         * guaranteed.</p>

         *

         * @param prefix the prefix that was being mapped.

         *      This is the empty string when a default mapping scope ends.

         * @throws org.xml.sax.SAXException the client may throw

         *            an exception during processing

         * @see #startPrefixMapping

         * @see #endElement

         */

        public void endPrefixMapping(String prefix) throws SAXException {



            checkClosed();



            //

        }



        /**

         * Receive notification of ignorable whitespace in element content.

         *

         * <p>Validating Parsers must use this method to report each chunk

         * of whitespace in element content (see the W3C XML 1.0

         * recommendation, section 2.10): non-validating parsers may also

         * use this method if they are capable of parsing and using

         * content models.</p>

         *

         * <p>SAX parsers may return all contiguous whitespace in a single

         * chunk, or they may split it into several chunks; however, all of

         * the characters in any single event must come from the same

         * external entity, so that the Locator provides useful

         * information.</p>

         *

         * <p>The application must not attempt to read from the array

         * outside of the specified range.</p>

         *

         * @param ch the characters from the XML document

         * @param start the start position in the array

         * @param length the number of characters to read from the array

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         * @see #characters

         */

        public void ignorableWhitespace(char[] ch, int start,

                                        int length) throws SAXException {

            characters(ch, start, length);

        }



        /**

         * Receive notification of a processing instruction.

         *

         * <p>The Parser will invoke this method once for each processing

         * instruction found: note that processing instructions may occur

         * before or after the main document element.</p>

         *

         * <p>A SAX parser must never report an XML declaration (XML 1.0,

         * section 2.8) or a text declaration (XML 1.0, section 4.3.1)

         * using this method.</p>

         *

         * <p>Like {@link #characters characters()}, processing instruction

         * data may have characters that need more than one
<code>char</code>

         * value. </p>

         *

         * @param target the processing instruction target

         * @param data the processing instruction data, or null if

         *        none was supplied.  The data does not include any

         *        whitespace separating it from the target

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         */

        public void processingInstruction(String target,

                String data) throws SAXException {



            checkClosed();



            try {

                this.writer.writeProcessingInstruction(target, data);

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }

        }



        /**

         * Receive an object for locating the origin of SAX document events.

         *

         * <p>SAX parsers are strongly encouraged (though not absolutely

         * required) to supply a locator: if it does so, it must supply

         * the locator to the application by invoking this method before

         * invoking any of the other methods in the ContentHandler

         * interface.</p>

         *

         * <p>The locator allows the application to determine the end

         * position of any document-related event, even if the parser is

         * not reporting an error.  Typically, the application will

         * use this information for reporting its own errors (such as

         * character content that does not match an application's

         * business rules).  The information returned by the locator

         * is probably not sufficient for use with a search engine.</p>

         *

         * <p>Note that the locator will return correct information only

         * during the invocation SAX event callbacks after

         * {@link #startDocument startDocument} returns and before

         * {@link #endDocument endDocument} is called.  The

         * application should not attempt to use it at any other time.</p>

         *

         * @param locator an object that can return the location of

         *                any SAX document event

         * @see org.xml.sax.Locator

         */

        public void setDocumentLocator(Locator locator) {

            this.locator = locator;

        }



        /**

         * Retrieves the Locator. <p>

         * @return the Locator

         */

        public Locator getDocumentLocator() {

            return this.locator;

        }



        /**

         * Receive notification of a skipped entity.

         * This is not called for entity references within markup constructs

         * such as element start tags or markup declarations.  (The XML

         * recommendation requires reporting skipped external entities.

         * SAX also reports internal entity expansion/non-expansion, except

         * within markup constructs.)

         *

         * <p>The Parser will invoke this method each time the entity is

         * skipped.  Non-validating processors may skip entities if they

         * have not seen the declarations (because, for example, the

         * entity was declared in an external DTD subset).  All processors

         * may skip external entities, depending on the values of the

         * <code>http://xml.org/sax/features/external-general-entities
</code>

         * and the

         * <code>http://xml.org/sax/features/external-parameter-entities
</code>

         * properties.</p>

         *

         * @param name the name of the skipped entity.  If it is a

         *        parameter entity, the name will begin with '%', and if

         *        it is the external DTD subset, it will be the string

         *        "[dtd]"

         * @throws org.xml.sax.SAXException any SAX exception, possibly

         *            wrapping another exception

         */

        public void skippedEntity(String name) throws SAXException {



            checkClosed();



            //

        }



        public void comment(char[] ch, int start,

                            int length) throws SAXException {



            checkClosed();



            try {

                this.writer.writeComment(new String(ch, start, length));

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }

        }



        public XMLStreamWriter getWriter() {

            return this.writer;

        }



        protected List<QualifiedName> getNamespaces() {

            return this.namespaces;

        }



        /**

         * Closes this object.

         */

        public void close() throws IOException {



            if (!this.closed) {

                this.closed = true;



                try {

                    this.writer.close();

                } catch (XMLStreamException e) {

                    throw new IOException(e);

                } finally {

                    this.writer     = null;

                    this.locator    = null;

                    this.namespaces = null;

                }

            }

        }



        /**

         * Retrieves whether this object is closed.

         */

        public boolean isClosed() {

            return this.closed;

        }



        /**

         * Checks whether this object is closed.

         *

         * @throws SAXException if this DOMBuilder is closed.

         */

        protected void checkClosed() throws SAXException {



            if (isClosed()) {

                throw new SAXException("content handler is closed.");    //
NOI18N

            }

        }



        // --------------------- internal implementation
-----------------------

        protected class QualifiedName {



            public final String namespaceName;

            public final String prefix;



            public QualifiedName(final String prefix,

                                 final String namespaceName) {

                this.prefix        = prefix;

                this.namespaceName = namespaceName;

            }

        }

    }

}

     And here is what it is all about(
http://java.sun.com/javase/6/docs/api/java/sql/class-use/SQLXML.html):


public interface java.sql.SQLXML{

    public abstract void free()       throws java.sql.SQLException;

    public abstract java.io.InputStream getBinaryStream()       throws
java.sql.SQLException;

    public abstract java.io.OutputStream setBinaryStream()       throws
java.sql.SQLException;

    public abstract java.io.Reader getCharacterStream()       throws
java.sql.SQLException;

    public abstract java.io.Writer setCharacterStream()       throws
java.sql.SQLException;

    public abstract java.lang.String getString()       throws
java.sql.SQLException;

    public abstract void setString(java.lang.String)       throws
java.sql.SQLException;

    public abstract javax.xml.transform.Source
getSource(java.lang.Class)       throws java.sql.SQLException;

    public abstract javax.xml.transform.Result
setResult(java.lang.Class)       throws java.sql.SQLException;

}



And now let's move a bit to PosgtreSQL, which has JDBC4 support:
    I found a JDBC4 implementation on their web site with an elephant on a
logo ;). After downloading I found org.postgresql.jdbc4.Jdbc4SQLXML.java:

package org.postgresql.jdbc4;

import org.postgresql.util.GT;
import org.postgresql.util.PSQLState;
import org.postgresql.util.PSQLException;
import org.postgresql.core.BaseConnection;

import java.io.*;
*import java.sql.SQLXML;*
import java.sql.SQLException;
*import javax.xml.transform.Source;*
*import javax.xml.transform.Result;*
*
*
*import javax.xml.transform.dom.DOMSource;*
*import javax.xml.transform.dom.DOMResult;*
*import javax.xml.parsers.DocumentBuilder;*
*import javax.xml.parsers.DocumentBuilderFactory;*
*import javax.xml.transform.Transformer;*
*import javax.xml.transform.TransformerFactory;*
*import javax.xml.transform.TransformerException;*
*
*
*import javax.xml.transform.sax.SAXSource;*
*import javax.xml.transform.sax.SAXResult;*
*import org.xml.sax.InputSource;*
*import org.xml.sax.ErrorHandler;*
*import org.xml.sax.SAXParseException;*
*import javax.xml.transform.sax.SAXTransformerFactory;*
*import javax.xml.transform.sax.TransformerHandler;*
*
*
*import javax.xml.transform.stream.StreamSource;*
*import javax.xml.transform.stream.StreamResult;*
*
*
*import javax.xml.transform.stax.StAXSource;*
*import javax.xml.transform.stax.StAXResult;*
*import javax.xml.stream.XMLInputFactory;*
*import javax.xml.stream.XMLOutputFactory;*
*import javax.xml.stream.XMLStreamReader;*
*import javax.xml.stream.XMLStreamWriter;*
*import javax.xml.stream.XMLStreamException;*

public class Jdbc4SQLXML implements SQLXML {

    private final BaseConnection _conn;
    private String _data;           // The actual data contained.
    private boolean _initialized;   // Has someone assigned the data for
this object?
    private boolean _active;        // Is anyone in the process of loading
data into us?
    private boolean _freed;

    private ByteArrayOutputStream _byteArrayOutputStream;
    private StringWriter _stringWriter;
    private DOMResult _domResult;

    *public Jdbc4SQLXML(BaseConnection conn)*
    {
        this(conn, null, false);
    }

*    public Jdbc4SQLXML(BaseConnection conn, String data)*
    {
        this(conn, data, true);
    }
*
*
*    private Jdbc4SQLXML(BaseConnection conn, String data, boolean
initialized)*
    {
        _conn = conn;
        _data = data;
        _initialized = initialized;
        _active = false;
        _freed = false;
    }
*
*
*    public synchronized void free()*
    {
        _freed = true;
        _data = null;
    }
*
*
*    public synchronized InputStream getBinaryStream() throws SQLException*
    {
        checkFreed();
        ensureInitialized();

        if (_data == null)
            return null;

        try {
            return new
ByteArrayInputStream(_conn.getEncoding().encode(_data));
        } catch (IOException ioe) {
            // This should be a can't happen exception.  We just
            // decoded this data, so it would be surprising that
            // we couldn't encode it.
            // For this reason don't make it translatable.
            throw new PSQLException("Failed to re-encode xml data.",
PSQLState.DATA_ERROR, ioe);
        }
    }
*
*
*    public synchronized Reader getCharacterStream() throws SQLException*
    {
        checkFreed();
        ensureInitialized();

        if (_data == null)
            return null;

        return new StringReader(_data);
    }

    // We must implement this unsafely because that's what the
    // interface requires.  Because it says we're returning T
    // which is unknown, none of the return values can satisfy it
    // as Java isn't going to understand the if statements that
    // ensure they are the same.
    //
    *public synchronized Source getSource(Class sourceClass) throws
SQLException*
*    *{
        checkFreed();
        ensureInitialized();

        if (_data == null)
            return null;

        try {
            if (sourceClass == null || DOMSource.class.equals(sourceClass))
            {
                DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = factory.newDocumentBuilder();
                builder.setErrorHandler(new NonPrintingErrorHandler());
                InputSource input = new InputSource(new
StringReader(_data));
                return new DOMSource(builder.parse(input));
            }
            else if (SAXSource.class.equals(sourceClass))
            {
                InputSource is = new InputSource(new StringReader(_data));
                return new SAXSource(is);
            }
            else if (StreamSource.class.equals(sourceClass))
            {
                return new StreamSource(new StringReader(_data));
            }
            else if (StAXSource.class.equals(sourceClass))
            {
                XMLInputFactory xif = XMLInputFactory.newInstance();
                XMLStreamReader xsr = xif.createXMLStreamReader(new
StringReader(_data));
                return new StAXSource(xsr);
            }
        } catch (Exception e) {
            throw new PSQLException(GT.tr("Unable to decode xml data."),
PSQLState.DATA_ERROR, e);
        }

        throw new PSQLException(GT.tr("Unknown XML Source class: {0}",
sourceClass), PSQLState.INVALID_PARAMETER_TYPE);
    }
*
*
*    public synchronized String getString() throws SQLException*
*    *{
        checkFreed();
        ensureInitialized();
        return _data;
    }
*
*
*    public synchronized OutputStream setBinaryStream() throws SQLException*
*    *{
        checkFreed();
        initialize();
        _active = true;
        _byteArrayOutputStream = new ByteArrayOutputStream();
        return _byteArrayOutputStream;
    }

    *public synchronized Writer setCharacterStream() throws SQLException*
    {
        checkFreed();
        initialize();
        _stringWriter = new StringWriter();
        return _stringWriter;
    }
*
*
*    public synchronized Result setResult(Class resultClass) throws
SQLException*
*    *{
        checkFreed();
        initialize();

        if (resultClass == null || DOMResult.class.equals(resultClass)) {
            _domResult = new DOMResult();
            _active = true;
            return _domResult;
        } else if (SAXResult.class.equals(resultClass)) {
            try {
                SAXTransformerFactory transformerFactory =
(SAXTransformerFactory)SAXTransformerFactory.newInstance();
                TransformerHandler transformerHandler =
transformerFactory.newTransformerHandler();
                _stringWriter = new StringWriter();
                transformerHandler.setResult(new
StreamResult(_stringWriter));
                _active = true;
                return new SAXResult(transformerHandler);
            } catch (TransformerException te) {
                throw new PSQLException(GT.tr("Unable to create SAXResult
for SQLXML."), PSQLState.UNEXPECTED_ERROR, te);
            }
        } else if (StreamResult.class.equals(resultClass)) {
            _stringWriter = new StringWriter();
            _active = true;
            return new StreamResult(_stringWriter);
        } else if (StAXResult.class.equals(resultClass)) {
            _stringWriter = new StringWriter();
            try {
                XMLOutputFactory xof = XMLOutputFactory.newInstance();
                XMLStreamWriter xsw =
xof.createXMLStreamWriter(_stringWriter);
                _active = true;
                return new StAXResult(xsw);
            } catch (XMLStreamException xse) {
                throw new PSQLException(GT.tr("Unable to create StAXResult
for SQLXML"), PSQLState.UNEXPECTED_ERROR, xse);
            }
        }

        throw new PSQLException(GT.tr("Unknown XML Result class: {0}",
resultClass), PSQLState.INVALID_PARAMETER_TYPE);
    }

    *public synchronized void setString(String value) throws SQLException*
*    *{
        checkFreed();
        initialize();
        _data = value;
    }

    *private void checkFreed() throws SQLException*
    {
        if (_freed) {
            throw new PSQLException(GT.tr("This SQLXML object has already
been freed."), PSQLState.OBJECT_NOT_IN_STATE);
        }
    }

    *private void ensureInitialized() throws SQLException*
    {
        if (!_initialized) {
            throw new PSQLException(GT.tr("This SQLXML object has not been
initialized, so you cannot retrieve data from it."),
PSQLState.OBJECT_NOT_IN_STATE);
        }

        // Is anyone loading data into us at the moment?
        if (!_active)
            return;

        if (_byteArrayOutputStream != null) {
            try {
                _data =
_conn.getEncoding().decode(_byteArrayOutputStream.toByteArray());
            } catch (IOException ioe) {
                throw new PSQLException(GT.tr("Failed to convert binary xml
data to encoding: {0}.", _conn.getEncoding().name()), PSQLState.DATA_ERROR,
ioe);
            } finally {
                _byteArrayOutputStream = null;
                _active = false;
            }
        } else if (_stringWriter != null) {
            // This is also handling the work for Stream, SAX, and StAX
Results
            // as they will use the same underlying stringwriter variable.
            //
            _data = _stringWriter.toString();
            _stringWriter = null;
            _active = false;
        } else if (_domResult != null) {
            // Copy the content from the result to a source
            // and use the identify transform to get it into a
            // friendlier result format.
            try {
                TransformerFactory factory =
TransformerFactory.newInstance();
                Transformer transformer = factory.newTransformer();
                DOMSource domSource = new DOMSource(_domResult.getNode());
                StringWriter stringWriter = new StringWriter();
                StreamResult streamResult = new StreamResult(stringWriter);
                transformer.transform(domSource, streamResult);
                _data = stringWriter.toString();
            } catch (TransformerException te) {
                throw new PSQLException(GT.tr("Unable to convert DOMResult
SQLXML data to a string."), PSQLState.DATA_ERROR, te);
            }
            finally {
                _domResult = null;
                _active = false;
            }
        }
    }


    *private void initialize() throws SQLException*
    {
        if (_initialized) {
            throw new PSQLException(GT.tr("This SQLXML object has already
been initialized, so you cannot manipulate it further."),
PSQLState.OBJECT_NOT_IN_STATE);
        }
        _initialized = true;
    }

    // Don't clutter System.err with errors the user can't silence.
    // If something bad really happens an exception will be thrown.
    *static class NonPrintingErrorHandler implements ErrorHandler*
    {
        public void error(SAXParseException e) { }
        public void fatalError(SAXParseException e) { }
        public void warning(SAXParseException e) { }
    }

}

In comparison to HyperSQL, I haven't found and SQLXML functions in
org.postgresql.jdbc4.JDBC4Connection.java or
org.postgresql.jdbc4.JDBC4ResultSet.java

I haven't found H2 database having SQLXML support yet. Only SQL functions
for processing/formatting data in XML format. Also a brief description of
SQLXML support in IBM's DB2
http://www.ibm.com/developerworks/data/library/techarticle/dm-0311wong/index.html

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message