xml.java

来自「derby database source code.good for you.」· Java 代码 · 共 862 行 · 第 1/2 页

JAVA
862
字号
/*   Derby - Class org.apache.derby.iapi.types.XML   Copyright 2005 The Apache Software Foundation or its licensors, as applicable.   Licensed under the Apache License, Version 2.0 (the "License");   you may not use this file except in compliance with the License.   You may obtain a copy of the License at      http://www.apache.org/licenses/LICENSE-2.0   Unless required by applicable law or agreed to in writing, software   distributed under the License is distributed on an "AS IS" BASIS,   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   See the License for the specific language governing permissions and   limitations under the License. */package org.apache.derby.iapi.types;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.services.cache.ClassSize;import org.apache.derby.iapi.services.io.ArrayInputStream;import org.apache.derby.iapi.services.io.StoredFormatIds;import org.apache.derby.iapi.services.io.StreamStorable;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.types.DataValueDescriptor;import org.apache.derby.iapi.types.StringDataValue;import org.apache.derby.iapi.types.BooleanDataValue;import org.apache.derby.iapi.reference.SQLState;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Types;import java.io.InputStream;import java.io.IOException;import java.io.ObjectOutput;import java.io.ObjectInput;import java.io.StringReader;import org.xml.sax.ErrorHandler;import org.xml.sax.XMLReader;import org.xml.sax.SAXException;import org.xml.sax.SAXParseException;import org.xml.sax.InputSource;import org.xml.sax.helpers.DefaultHandler;import org.xml.sax.helpers.XMLReaderFactory;import javax.xml.transform.Templates;import javax.xml.transform.TransformerFactory;import javax.xml.transform.sax.SAXResult;import javax.xml.transform.sax.TemplatesHandler;import javax.xml.transform.sax.TransformerHandler;// Note that even though the following has a Xalan// package name, it IS part of the JDK 1.4 API, and// thus we can compile it without having Xalan in// our classpath.import org.apache.xalan.processor.TransformerFactoryImpl;/** * This type implements the XMLDataValue interface and thus is * the type on which all XML related operations are executed. * * The first and simplest XML store implementation is a UTF-8 * based one--all XML data is stored on disk as a UTF-8 string, * just like the other Derby string types.  In order to make * it possible for smarter XML implementations to exist in * the future, this class always writes an "XML implementation * id" to disk before writing the rest of its data.  When * reading the data, the impl id is read first and serves * as an indicator of how the rest of the data should be * read. * * So long as there's only one implementation (UTF-8) * the impl id can be ignored; but when smarter implementations * are written, the impl id will be the key to figuring out * how an XML value should be read, written, and processed. */public class XML    extends DataType implements XMLDataValue, StreamStorable{    // Id for this implementation.  Should be unique    // across all XML type implementations.    protected static final short UTF8_IMPL_ID = 0;    // Parser class to use for parsing XML.  We use the    // Xerces parser, so (for now) we require that Xerces    // be in the user's classpath.  Note that we load    // the Xerces class dynamically (using the class     // name) so that Derby will build even if Xerces    // isn't in the build environment; i.e. Xerces is    // only required if XML is actually going to be used    // at runtime; it's not required for a successful    // build nor for non-XML database use.    protected static final String XML_PARSER_CLASS =        "org.apache.xerces.parsers.SAXParser";    // Guess at how much memory this type will take.    private static final int BASE_MEMORY_USAGE =        ClassSize.estimateBaseFromCatalog(XML.class);    // The actual XML data in this implementation is just a simple    // string, so this class really just wraps a SQLChar and    // defers most calls to the corresponding calls on that    // SQLChar.  Note that, even though a SQLChar is the    // underlying implementation, an XML value is nonetheless    // NOT considered comparable nor compatible with any of    // Derby string types.    private SQLChar xmlStringValue;    // An XML reader for reading and parsing SAX events.    protected XMLReader saxReader;    // XSLT objects used when performing an XSLT query, which    // is the query mechanism for this UTF8-based implementation.    private static final String XPATH_PLACEHOLDER = "XPATH_PLACEHOLDER";    private static final String QUERY_MATCH_STRING = "MATCH";    private static String xsltStylesheet;    private XMLReader xsltReader;    private TransformerFactoryImpl saxTFactory;    /**     * Default constructor.     */    public XML()    {        xmlStringValue = null;    }    /**     * Private constructor used for the getClone() method.     * Takes a SQLChar and clones it.     * @param val A SQLChar instance to clone and use for     *  this XML value.     */    private XML(SQLChar val)    {        xmlStringValue = (val == null ? null : (SQLChar)val.getClone());    }    /* ****     * DataValueDescriptor interface.     * */    /**     * @see DataValueDescriptor#getClone     */    public DataValueDescriptor getClone()    {        return new XML(xmlStringValue);    }    /**     * @see DataValueDescriptor#getNewNull     */    public DataValueDescriptor getNewNull()    {        return new XML();    }    /**     * @see DataValueDescriptor#getTypeName     */    public String getTypeName()    {        return TypeId.XML_NAME;    }    /**     * @see DataValueDescriptor#typePrecedence     */    public int typePrecedence()    {        return TypeId.XML_PRECEDENCE;    }    /**     * @see DataValueDescriptor#getString     */    public String getString() throws StandardException    {        return (xmlStringValue == null) ? null : xmlStringValue.getString();    }    /**     * @see DataValueDescriptor#getLength     */    public int    getLength() throws StandardException    {        return ((xmlStringValue == null) ? 0 : xmlStringValue.getLength());    }    /**      * @see DataValueDescriptor#estimateMemoryUsage     */    public int estimateMemoryUsage()    {        int sz = BASE_MEMORY_USAGE;        if (xmlStringValue != null)            sz += xmlStringValue.estimateMemoryUsage();        return sz;    }    /**     * @see DataValueDescriptor#readExternalFromArray     */    public void readExternalFromArray(ArrayInputStream in)        throws IOException    {        if (xmlStringValue == null)            xmlStringValue = new SQLChar();        // Read the XML implementation id.  Right now there's        // only one implementation (UTF-8 based), so we don't        // use this value.  But if better implementations come        // up in the future, we'll have to use this impl id to        // figure out how to read the data.        in.readShort();        // Now just read the XML data as UTF-8.        xmlStringValue.readExternalFromArray(in);    }    /**     * @see DataValueDescriptor#setFrom     */    protected void setFrom(DataValueDescriptor theValue)        throws StandardException    {        if (xmlStringValue == null)            xmlStringValue = new SQLChar();        xmlStringValue.setValue(theValue.getString());    }    /**      * @see DataValueDescriptor#setValueFromResultSet      */    public final void setValueFromResultSet(        ResultSet resultSet, int colNumber, boolean isNullable)        throws SQLException    {        if (xmlStringValue == null)            xmlStringValue = new SQLChar();        xmlStringValue.setValue(resultSet.getString(colNumber));    }    /**     * Compare two XML DataValueDescriptors.  NOTE: This method     * should only be used by the database store for the purpose of     * index positioning--comparisons of XML type are not allowed     * from the language side of things.  That said, all store     * wants to do is order the NULLs, so we don't actually     * have to do a full comparison.  Just return an order     * value based on whether or not this XML value and the     * other XML value are null.  As mentioned in the "compare"     * method of DataValueDescriptor, nulls are considered     * equal to other nulls and less than all other values.     *     * An example of when this method might be used is if the     * user executed a query like:     *     * select i from x_table where x_col is not null     *     * @see DataValueDescriptor#compare     */    public int compare(DataValueDescriptor other)        throws StandardException    {        if (SanityManager.DEBUG) {            SanityManager.ASSERT(other instanceof XMLDataValue,                "Store should NOT have tried to compare an XML value " +                "with a non-XML value.");        }        if (isNull()) {            if (other.isNull())            // both null, so call them 'equal'.                return 0;            // This XML is 'less than' the other.            return -1;        }        if (other.isNull())        // This XML is 'greater than' the other.            return 1;        // Two non-null values: we shouldn't ever get here,        // since that would necessitate a comparsion of XML        // values, which isn't allowed.        if (SanityManager.DEBUG) {            SanityManager.THROWASSERT(                "Store tried to compare two non-null XML values, " +                "which isn't allowed.");        }        return 0;    }    /* ****     * Storable interface, implies Externalizable, TypedFormat     */    /**     * @see TypedFormat#getTypeFormatId     *     * From the engine's perspective, all XML implementations share     * the same format id.     */    public int getTypeFormatId() {        return StoredFormatIds.XML_ID;    }    /**     * @see Storable#isNull     */    public boolean isNull()    {        return ((xmlStringValue == null) || xmlStringValue.isNull());    }    /**     * @see Storable#restoreToNull     */    public void restoreToNull()    {        if (xmlStringValue != null)            xmlStringValue.restoreToNull();    }    /**     * Read an XML value from an input stream.     * @param in The stream from which we're reading.     */    public void readExternal(ObjectInput in) throws IOException    {        if (xmlStringValue == null)            xmlStringValue = new SQLChar();        // Read the XML implementation id.  Right now there's        // only one implementation (UTF-8 based), so we don't        // use this value.  But if better implementations come        // up in the future, we'll have to use this impl id to        // figure out how to read the data.        in.readShort();        // Now just read the XML data as UTF-8.        xmlStringValue.readExternal(in);    }    /**     * Write an XML value.      * @param out The stream to which we're writing.     */    public void writeExternal(ObjectOutput out) throws IOException    {        // never called when value is null        if (SanityManager.DEBUG)            SanityManager.ASSERT(!isNull());        // Write out the XML store impl id.        out.writeShort(UTF8_IMPL_ID);        // Now write out the data.        xmlStringValue.writeExternal(out);    }    /* ****     * StreamStorable interface     * */    /**     * @see StreamStorable#returnStream     */    public InputStream returnStream()    {        return            (xmlStringValue == null) ? null : xmlStringValue.returnStream();    }    /**     * @see StreamStorable#setStream     */    public void setStream(InputStream newStream)    {        if (xmlStringValue == null)            xmlStringValue = new SQLChar();        // The stream that we receive is for an XML data value,        // which means it has an XML implementation id stored        // at the front (we put it there when we wrote it out).        // If we leave that there we'll get a failure when        // our underlying SQLChar tries to read from the        // stream, because the extra impl id will throw        // off the UTF format.  So we need to read in (and        // ignore) the impl id before using the stream.        try {            // 2 bytes equal a short, which is what an impl id is.            newStream.read();            newStream.read();        } catch (Exception e) {            if (SanityManager.DEBUG)                SanityManager.THROWASSERT("Failed to read impl id" +                    "bytes in setStream.");        }        // Now go ahead and use the stream.        xmlStringValue.setStream(newStream);    }    /**     * @see StreamStorable#loadStream     */    public void loadStream() throws StandardException    {        getString();    }    /* ****     * XMLDataValue interface.     * */    /**     * Method to parse an XML string and, if it's valid,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?