提交 4ab17280 编写于 作者: J joehw

8004371: (props) Properties.loadFromXML needs small footprint XML parser as...

8004371: (props) Properties.loadFromXML needs small footprint XML parser as fallback when JAXP is not present
Reviewed-by: alanb, mchung, psandoz
上级 7352c405
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// Attributes.java - attribute list with Namespace support
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
// $Id: Attributes.java,v 1.2 2004/11/03 22:44:51 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Interface for a list of XML attributes.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>This interface allows access to a list of attributes in
* three different ways:</p>
*
* <ol>
* <li>by attribute index;</li>
* <li>by Namespace-qualified name; or</li>
* <li>by qualified (prefixed) name.</li>
* </ol>
*
* <p>The list will not contain attributes that were declared
* #IMPLIED but not specified in the start tag. It will also not
* contain attributes used as Namespace declarations (xmlns*) unless
* the <code>http://xml.org/sax/features/namespace-prefixes</code>
* feature is set to <var>true</var> (it is <var>false</var> by
* default).
* Because SAX2 conforms to the original "Namespaces in XML"
* recommendation, it normally does not
* give namespace declaration attributes a namespace URI.
* </p>
*
* <p>Some SAX2 parsers may support using an optional feature flag
* (<code>http://xml.org/sax/features/xmlns-uris</code>) to request
* that those attributes be given URIs, conforming to a later
* backwards-incompatible revision of that recommendation. (The
* attribute's "local name" will be the prefix, or "xmlns" when
* defining a default element namespace.) For portability, handler
* code should always resolve that conflict, rather than requiring
* parsers that can change the setting of that feature flag. </p>
*
* <p>If the namespace-prefixes feature (see above) is
* <var>false</var>, access by qualified name may not be available; if
* the <code>http://xml.org/sax/features/namespaces</code> feature is
* <var>false</var>, access by Namespace-qualified names may not be
* available.</p>
*
* <p>This interface replaces the now-deprecated SAX1 {@link
* org.xml.sax.AttributeList AttributeList} interface, which does not
* contain Namespace support. In addition to Namespace support, it
* adds the <var>getIndex</var> methods (below).</p>
*
* <p>The order of attributes in the list is unspecified, and will
* vary from implementation to implementation.</p>
*
* @since SAX 2.0
* @author David Megginson
* @see org.xml.sax.helpers.AttributesImpl
* @see org.xml.sax.ext.DeclHandler#attributeDecl
*/
public interface Attributes
{
////////////////////////////////////////////////////////////////////
// Indexed access.
////////////////////////////////////////////////////////////////////
/**
* Return the number of attributes in the list.
*
* <p>Once you know the number of attributes, you can iterate
* through the list.</p>
*
* @return The number of attributes in the list.
* @see #getURI(int)
* @see #getLocalName(int)
* @see #getQName(int)
* @see #getType(int)
* @see #getValue(int)
*/
public abstract int getLength ();
/**
* Look up an attribute's Namespace URI by index.
*
* @param index The attribute index (zero-based).
* @return The Namespace URI, or the empty string if none
* is available, or null if the index is out of
* range.
* @see #getLength
*/
public abstract String getURI (int index);
/**
* Look up an attribute's local name by index.
*
* @param index The attribute index (zero-based).
* @return The local name, or the empty string if Namespace
* processing is not being performed, or null
* if the index is out of range.
* @see #getLength
*/
public abstract String getLocalName (int index);
/**
* Look up an attribute's XML qualified (prefixed) name by index.
*
* @param index The attribute index (zero-based).
* @return The XML qualified name, or the empty string
* if none is available, or null if the index
* is out of range.
* @see #getLength
*/
public abstract String getQName (int index);
/**
* Look up an attribute's type by index.
*
* <p>The attribute type is one of the strings "CDATA", "ID",
* "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES",
* or "NOTATION" (always in upper case).</p>
*
* <p>If the parser has not read a declaration for the attribute,
* or if the parser does not report attribute types, then it must
* return the value "CDATA" as stated in the XML 1.0 Recommendation
* (clause 3.3.3, "Attribute-Value Normalization").</p>
*
* <p>For an enumerated attribute that is not a notation, the
* parser will report the type as "NMTOKEN".</p>
*
* @param index The attribute index (zero-based).
* @return The attribute's type as a string, or null if the
* index is out of range.
* @see #getLength
*/
public abstract String getType (int index);
/**
* Look up an attribute's value by index.
*
* <p>If the attribute value is a list of tokens (IDREFS,
* ENTITIES, or NMTOKENS), the tokens will be concatenated
* into a single string with each token separated by a
* single space.</p>
*
* @param index The attribute index (zero-based).
* @return The attribute's value as a string, or null if the
* index is out of range.
* @see #getLength
*/
public abstract String getValue (int index);
////////////////////////////////////////////////////////////////////
// Name-based query.
////////////////////////////////////////////////////////////////////
/**
* Look up the index of an attribute by Namespace name.
*
* @param uri The Namespace URI, or the empty string if
* the name has no Namespace URI.
* @param localName The attribute's local name.
* @return The index of the attribute, or -1 if it does not
* appear in the list.
*/
public int getIndex (String uri, String localName);
/**
* Look up the index of an attribute by XML qualified (prefixed) name.
*
* @param qName The qualified (prefixed) name.
* @return The index of the attribute, or -1 if it does not
* appear in the list.
*/
public int getIndex (String qName);
/**
* Look up an attribute's type by Namespace name.
*
* <p>See {@link #getType(int) getType(int)} for a description
* of the possible types.</p>
*
* @param uri The Namespace URI, or the empty String if the
* name has no Namespace URI.
* @param localName The local name of the attribute.
* @return The attribute type as a string, or null if the
* attribute is not in the list or if Namespace
* processing is not being performed.
*/
public abstract String getType (String uri, String localName);
/**
* Look up an attribute's type by XML qualified (prefixed) name.
*
* <p>See {@link #getType(int) getType(int)} for a description
* of the possible types.</p>
*
* @param qName The XML qualified name.
* @return The attribute type as a string, or null if the
* attribute is not in the list or if qualified names
* are not available.
*/
public abstract String getType (String qName);
/**
* Look up an attribute's value by Namespace name.
*
* <p>See {@link #getValue(int) getValue(int)} for a description
* of the possible values.</p>
*
* @param uri The Namespace URI, or the empty String if the
* name has no Namespace URI.
* @param localName The local name of the attribute.
* @return The attribute value as a string, or null if the
* attribute is not in the list.
*/
public abstract String getValue (String uri, String localName);
/**
* Look up an attribute's value by XML qualified (prefixed) name.
*
* <p>See {@link #getValue(int) getValue(int)} for a description
* of the possible values.</p>
*
* @param qName The XML qualified name.
* @return The attribute value as a string, or null if the
* attribute is not in the list or if qualified names
* are not available.
*/
public abstract String getValue (String qName);
}
// end of Attributes.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// ContentHandler.java - handle main document content.
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
// $Id: ContentHandler.java,v 1.2 2004/11/03 22:44:51 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Receive notification of the logical content of a document.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>This is the main interface that most SAX applications
* implement: if the application needs to be informed of basic parsing
* events, it implements this interface and registers an instance with
* the SAX parser using the {@link org.xml.sax.XMLReader#setContentHandler
* setContentHandler} method. The parser uses the instance to report
* basic document-related events like the start and end of elements
* and character data.</p>
*
* <p>The order of events in this interface is very important, and
* mirrors the order of information in the document itself. For
* example, all of an element's content (character data, processing
* instructions, and/or subelements) will appear, in order, between
* the startElement event and the corresponding endElement event.</p>
*
* <p>This interface is similar to the now-deprecated SAX 1.0
* DocumentHandler interface, but it adds support for Namespaces
* and for reporting skipped entities (in non-validating XML
* processors).</p>
*
* <p>Implementors should note that there is also a
* <code>ContentHandler</code> class in the <code>java.net</code>
* package; that means that it's probably a bad idea to do</p>
*
* <pre>import java.net.*;
* import org.xml.sax.*;
* </pre>
*
* <p>In fact, "import ...*" is usually a sign of sloppy programming
* anyway, so the user should consider this a feature rather than a
* bug.</p>
*
* @since SAX 2.0
* @author David Megginson
* @see org.xml.sax.XMLReader
* @see org.xml.sax.DTDHandler
* @see org.xml.sax.ErrorHandler
*/
public interface ContentHandler
{
/**
* 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);
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
}
// end of ContentHandler.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAX DTD handler.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
// $Id: DTDHandler.java,v 1.2 2004/11/03 22:44:51 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Receive notification of basic DTD-related events.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>If a SAX application needs information about notations and
* unparsed entities, then the application implements this
* interface and registers an instance with the SAX parser using
* the parser's setDTDHandler method. The parser uses the
* instance to report notation and unparsed entity declarations to
* the application.</p>
*
* <p>Note that this interface includes only those DTD events that
* the XML recommendation <em>requires</em> processors to report:
* notation and unparsed entity declarations.</p>
*
* <p>The SAX parser may report these events in any order, regardless
* of the order in which the notations and unparsed entities were
* declared; however, all DTD events must be reported after the
* document handler's startDocument event, and before the first
* startElement event.
* (If the {@link org.xml.sax.ext.LexicalHandler LexicalHandler} is
* used, these events must also be reported before the endDTD event.)
* </p>
*
* <p>It is up to the application to store the information for
* future use (perhaps in a hash table or object tree).
* If the application encounters attributes of type "NOTATION",
* "ENTITY", or "ENTITIES", it can use the information that it
* obtained through this interface to find the entity and/or
* notation corresponding with the attribute value.</p>
*
* @since SAX 1.0
* @author David Megginson
* @see org.xml.sax.XMLReader#setDTDHandler
*/
public interface DTDHandler {
/**
* Receive notification of a notation declaration event.
*
* <p>It is up to the application to record the notation for later
* reference, if necessary;
* notations may appear as attribute values and in unparsed entity
* declarations, and are sometime used with processing instruction
* target names.</p>
*
* <p>At least one of publicId and systemId must be non-null.
* If a system identifier is present, and it is a URL, the SAX
* parser must resolve it fully before passing it to the
* application through this event.</p>
*
* <p>There is no guarantee that the notation declaration will be
* reported before any unparsed entities that use it.</p>
*
* @param name The notation name.
* @param publicId The notation's public identifier, or null if
* none was given.
* @param systemId The notation's system identifier, or null if
* none was given.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see #unparsedEntityDecl
* @see org.xml.sax.Attributes
*/
public abstract void notationDecl (String name,
String publicId,
String systemId)
throws SAXException;
/**
* Receive notification of an unparsed entity declaration event.
*
* <p>Note that the notation name corresponds to a notation
* reported by the {@link #notationDecl notationDecl} event.
* It is up to the application to record the entity for later
* reference, if necessary;
* unparsed entities may appear as attribute values.
* </p>
*
* <p>If the system identifier is a URL, the parser must resolve it
* fully before passing it to the application.</p>
*
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @param name The unparsed entity's name.
* @param publicId The entity's public identifier, or null if none
* was given.
* @param systemId The entity's system identifier.
* @param notationName The name of the associated notation.
* @see #notationDecl
* @see org.xml.sax.Attributes
*/
public abstract void unparsedEntityDecl (String name,
String publicId,
String systemId,
String notationName)
throws SAXException;
}
// end of DTDHandler.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAX entity resolver.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
// $Id: EntityResolver.java,v 1.2 2004/11/03 22:44:52 jsuttor Exp $
package jdk.internal.org.xml.sax;
import java.io.IOException;
/**
* Basic interface for resolving entities.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>If a SAX application needs to implement customized handling
* for external entities, it must implement this interface and
* register an instance with the SAX driver using the
* {@link org.xml.sax.XMLReader#setEntityResolver setEntityResolver}
* method.</p>
*
* <p>The XML reader will then allow the application to intercept any
* external entities (including the external DTD subset and external
* parameter entities, if any) before including them.</p>
*
* <p>Many SAX applications will not need to implement this interface,
* but it will be especially useful for applications that build
* XML documents from databases or other specialised input sources,
* or for applications that use URI types other than URLs.</p>
*
* <p>The following resolver would provide the application
* with a special character stream for the entity with the system
* identifier "http://www.myhost.com/today":</p>
*
* <pre>
* import org.xml.sax.EntityResolver;
* import org.xml.sax.InputSource;
*
* public class MyResolver implements EntityResolver {
* public InputSource resolveEntity (String publicId, String systemId)
* {
* if (systemId.equals("http://www.myhost.com/today")) {
* // return a special input source
* MyReader reader = new MyReader();
* return new InputSource(reader);
* } else {
* // use the default behaviour
* return null;
* }
* }
* }
* </pre>
*
* <p>The application can also use this interface to redirect system
* identifiers to local URIs or to look up replacements in a catalog
* (possibly by using the public identifier).</p>
*
* @since SAX 1.0
* @author David Megginson
* @see org.xml.sax.XMLReader#setEntityResolver
* @see org.xml.sax.InputSource
*/
public interface EntityResolver {
/**
* Allow the application to resolve external entities.
*
* <p>The parser will call this method before opening any external
* entity except the top-level document entity. Such entities include
* the external DTD subset and external parameter entities referenced
* within the DTD (in either case, only if the parser reads external
* parameter entities), and external general entities referenced
* within the document element (if the parser reads external general
* entities). The application may request that the parser locate
* the entity itself, that it use an alternative URI, or that it
* use data provided by the application (as a character or byte
* input stream).</p>
*
* <p>Application writers can use this method to redirect external
* system identifiers to secure and/or local URIs, to look up
* public identifiers in a catalogue, or to read an entity from a
* database or other input source (including, for example, a dialog
* box). Neither XML nor SAX specifies a preferred policy for using
* public or system IDs to resolve resources. However, SAX specifies
* how to interpret any InputSource returned by this method, and that
* if none is returned, then the system ID will be dereferenced as
* a URL. </p>
*
* <p>If the system identifier is a URL, the SAX parser must
* resolve it fully before reporting it to the application.</p>
*
* @param publicId The public identifier of the external entity
* being referenced, or null if none was supplied.
* @param systemId The system identifier of the external entity
* being referenced.
* @return An InputSource object describing the new input source,
* or null to request that the parser open a regular
* URI connection to the system identifier.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @exception java.io.IOException A Java-specific IO exception,
* possibly the result of creating a new InputStream
* or Reader for the InputSource.
* @see org.xml.sax.InputSource
*/
public abstract InputSource resolveEntity (String publicId,
String systemId)
throws SAXException, IOException;
}
// end of EntityResolver.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAX error handler.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
// $Id: ErrorHandler.java,v 1.2 2004/11/03 22:44:52 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Basic interface for SAX error handlers.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>If a SAX application needs to implement customized error
* handling, it must implement this interface and then register an
* instance with the XML reader using the
* {@link org.xml.sax.XMLReader#setErrorHandler setErrorHandler}
* method. The parser will then report all errors and warnings
* through this interface.</p>
*
* <p><strong>WARNING:</strong> If an application does <em>not</em>
* register an ErrorHandler, XML parsing errors will go unreported,
* except that <em>SAXParseException</em>s will be thrown for fatal errors.
* In order to detect validity errors, an ErrorHandler that does something
* with {@link #error error()} calls must be registered.</p>
*
* <p>For XML processing errors, a SAX driver must use this interface
* in preference to throwing an exception: it is up to the application
* to decide whether to throw an exception for different types of
* errors and warnings. Note, however, that there is no requirement that
* the parser continue to report additional errors after a call to
* {@link #fatalError fatalError}. In other words, a SAX driver class
* may throw an exception after reporting any fatalError.
* Also parsers may throw appropriate exceptions for non-XML errors.
* For example, {@link XMLReader#parse XMLReader.parse()} would throw
* an IOException for errors accessing entities or the document.</p>
*
* @since SAX 1.0
* @author David Megginson
* @see org.xml.sax.XMLReader#setErrorHandler
* @see org.xml.sax.SAXParseException
*/
public interface ErrorHandler {
/**
* Receive notification of a warning.
*
* <p>SAX parsers will use this method to report conditions that
* are not errors or fatal errors as defined by the XML
* recommendation. The default behaviour is to take no
* action.</p>
*
* <p>The SAX parser must continue to provide normal parsing events
* after invoking this method: it should still be possible for the
* application to process the document through to the end.</p>
*
* <p>Filters may use this method to report other, non-XML warnings
* as well.</p>
*
* @param exception The warning information encapsulated in a
* SAX parse exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.SAXParseException
*/
public abstract void warning (SAXParseException exception)
throws SAXException;
/**
* Receive notification of a recoverable error.
*
* <p>This corresponds to the definition of "error" in section 1.2
* of the W3C XML 1.0 Recommendation. For example, a validating
* parser would use this callback to report the violation of a
* validity constraint. The default behaviour is to take no
* action.</p>
*
* <p>The SAX parser must continue to provide normal parsing
* events after invoking this method: it should still be possible
* for the application to process the document through to the end.
* If the application cannot do so, then the parser should report
* a fatal error even if the XML recommendation does not require
* it to do so.</p>
*
* <p>Filters may use this method to report other, non-XML errors
* as well.</p>
*
* @param exception The error information encapsulated in a
* SAX parse exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.SAXParseException
*/
public abstract void error (SAXParseException exception)
throws SAXException;
/**
* Receive notification of a non-recoverable error.
*
* <p><strong>There is an apparent contradiction between the
* documentation for this method and the documentation for {@link
* org.xml.sax.ContentHandler#endDocument}. 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>This corresponds to the definition of "fatal error" in
* section 1.2 of the W3C XML 1.0 Recommendation. For example, a
* parser would use this callback to report the violation of a
* well-formedness constraint.</p>
*
* <p>The application must assume that the document is unusable
* after the parser has invoked this method, and should continue
* (if at all) only for the sake of collecting additional error
* messages: in fact, SAX parsers are free to stop reporting any
* other events once this method has been invoked.</p>
*
* @param exception The error information encapsulated in a
* SAX parse exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.SAXParseException
*/
public abstract void fatalError (SAXParseException exception)
throws SAXException;
}
// end of ErrorHandler.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAX input source.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
// $Id: InputSource.java,v 1.2 2004/11/03 22:55:32 jsuttor Exp $
package jdk.internal.org.xml.sax;
import java.io.Reader;
import java.io.InputStream;
/**
* A single input source for an XML entity.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>This class allows a SAX application to encapsulate information
* about an input source in a single object, which may include
* a public identifier, a system identifier, a byte stream (possibly
* with a specified encoding), and/or a character stream.</p>
*
* <p>There are two places that the application can deliver an
* input source to the parser: as the argument to the Parser.parse
* method, or as the return value of the EntityResolver.resolveEntity
* method.</p>
*
* <p>The SAX parser will use the InputSource object to determine how
* to read XML input. If there is a character stream available, the
* parser will read that stream directly, disregarding any text
* encoding declaration found in that stream.
* If there is no character stream, but there is
* a byte stream, the parser will use that byte stream, using the
* encoding specified in the InputSource or else (if no encoding is
* specified) autodetecting the character encoding using an algorithm
* such as the one in the XML specification. If neither a character
* stream nor a
* byte stream is available, the parser will attempt to open a URI
* connection to the resource identified by the system
* identifier.</p>
*
* <p>An InputSource object belongs to the application: the SAX parser
* shall never modify it in any way (it may modify a copy if
* necessary). However, standard processing of both byte and
* character streams is to close them on as part of end-of-parse cleanup,
* so applications should not attempt to re-use such streams after they
* have been handed to a parser. </p>
*
* @since SAX 1.0
* @author David Megginson
* @see org.xml.sax.XMLReader#parse(org.xml.sax.InputSource)
* @see org.xml.sax.EntityResolver#resolveEntity
* @see java.io.InputStream
* @see java.io.Reader
*/
public class InputSource {
/**
* Zero-argument default constructor.
*
* @see #setPublicId
* @see #setSystemId
* @see #setByteStream
* @see #setCharacterStream
* @see #setEncoding
*/
public InputSource ()
{
}
/**
* Create a new input source with a system identifier.
*
* <p>Applications may use setPublicId to include a
* public identifier as well, or setEncoding to specify
* the character encoding, if known.</p>
*
* <p>If the system identifier is a URL, it must be fully
* resolved (it may not be a relative URL).</p>
*
* @param systemId The system identifier (URI).
* @see #setPublicId
* @see #setSystemId
* @see #setByteStream
* @see #setEncoding
* @see #setCharacterStream
*/
public InputSource (String systemId)
{
setSystemId(systemId);
}
/**
* Create a new input source with a byte stream.
*
* <p>Application writers should use setSystemId() to provide a base
* for resolving relative URIs, may use setPublicId to include a
* public identifier, and may use setEncoding to specify the object's
* character encoding.</p>
*
* @param byteStream The raw byte stream containing the document.
* @see #setPublicId
* @see #setSystemId
* @see #setEncoding
* @see #setByteStream
* @see #setCharacterStream
*/
public InputSource (InputStream byteStream)
{
setByteStream(byteStream);
}
/**
* Create a new input source with a character stream.
*
* <p>Application writers should use setSystemId() to provide a base
* for resolving relative URIs, and may use setPublicId to include a
* public identifier.</p>
*
* <p>The character stream shall not include a byte order mark.</p>
*
* @see #setPublicId
* @see #setSystemId
* @see #setByteStream
* @see #setCharacterStream
*/
public InputSource (Reader characterStream)
{
setCharacterStream(characterStream);
}
/**
* Set the public identifier for this input source.
*
* <p>The public identifier is always optional: if the application
* writer includes one, it will be provided as part of the
* location information.</p>
*
* @param publicId The public identifier as a string.
* @see #getPublicId
* @see org.xml.sax.Locator#getPublicId
* @see org.xml.sax.SAXParseException#getPublicId
*/
public void setPublicId (String publicId)
{
this.publicId = publicId;
}
/**
* Get the public identifier for this input source.
*
* @return The public identifier, or null if none was supplied.
* @see #setPublicId
*/
public String getPublicId ()
{
return publicId;
}
/**
* Set the system identifier for this input source.
*
* <p>The system identifier is optional if there is a byte stream
* or a character stream, but it is still useful to provide one,
* since the application can use it to resolve relative URIs
* and can include it in error messages and warnings (the parser
* will attempt to open a connection to the URI only if
* there is no byte stream or character stream specified).</p>
*
* <p>If the application knows the character encoding of the
* object pointed to by the system identifier, it can register
* the encoding using the setEncoding method.</p>
*
* <p>If the system identifier is a URL, it must be fully
* resolved (it may not be a relative URL).</p>
*
* @param systemId The system identifier as a string.
* @see #setEncoding
* @see #getSystemId
* @see org.xml.sax.Locator#getSystemId
* @see org.xml.sax.SAXParseException#getSystemId
*/
public void setSystemId (String systemId)
{
this.systemId = systemId;
}
/**
* Get the system identifier for this input source.
*
* <p>The getEncoding method will return the character encoding
* of the object pointed to, or null if unknown.</p>
*
* <p>If the system ID is a URL, it will be fully resolved.</p>
*
* @return The system identifier, or null if none was supplied.
* @see #setSystemId
* @see #getEncoding
*/
public String getSystemId ()
{
return systemId;
}
/**
* Set the byte stream for this input source.
*
* <p>The SAX parser will ignore this if there is also a character
* stream specified, but it will use a byte stream in preference
* to opening a URI connection itself.</p>
*
* <p>If the application knows the character encoding of the
* byte stream, it should set it with the setEncoding method.</p>
*
* @param byteStream A byte stream containing an XML document or
* other entity.
* @see #setEncoding
* @see #getByteStream
* @see #getEncoding
* @see java.io.InputStream
*/
public void setByteStream (InputStream byteStream)
{
this.byteStream = byteStream;
}
/**
* Get the byte stream for this input source.
*
* <p>The getEncoding method will return the character
* encoding for this byte stream, or null if unknown.</p>
*
* @return The byte stream, or null if none was supplied.
* @see #getEncoding
* @see #setByteStream
*/
public InputStream getByteStream ()
{
return byteStream;
}
/**
* Set the character encoding, if known.
*
* <p>The encoding must be a string acceptable for an
* XML encoding declaration (see section 4.3.3 of the XML 1.0
* recommendation).</p>
*
* <p>This method has no effect when the application provides a
* character stream.</p>
*
* @param encoding A string describing the character encoding.
* @see #setSystemId
* @see #setByteStream
* @see #getEncoding
*/
public void setEncoding (String encoding)
{
this.encoding = encoding;
}
/**
* Get the character encoding for a byte stream or URI.
* This value will be ignored when the application provides a
* character stream.
*
* @return The encoding, or null if none was supplied.
* @see #setByteStream
* @see #getSystemId
* @see #getByteStream
*/
public String getEncoding ()
{
return encoding;
}
/**
* Set the character stream for this input source.
*
* <p>If there is a character stream specified, the SAX parser
* will ignore any byte stream and will not attempt to open
* a URI connection to the system identifier.</p>
*
* @param characterStream The character stream containing the
* XML document or other entity.
* @see #getCharacterStream
* @see java.io.Reader
*/
public void setCharacterStream (Reader characterStream)
{
this.characterStream = characterStream;
}
/**
* Get the character stream for this input source.
*
* @return The character stream, or null if none was supplied.
* @see #setCharacterStream
*/
public Reader getCharacterStream ()
{
return characterStream;
}
////////////////////////////////////////////////////////////////////
// Internal state.
////////////////////////////////////////////////////////////////////
private String publicId;
private String systemId;
private InputStream byteStream;
private String encoding;
private Reader characterStream;
}
// end of InputSource.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAX locator interface for document events.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
// $Id: Locator.java,v 1.2 2004/11/03 22:55:32 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Interface for associating a SAX event with a document location.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>If a SAX parser provides location information to the SAX
* application, it does so by implementing this interface and then
* passing an instance to the application using the content
* handler's {@link org.xml.sax.ContentHandler#setDocumentLocator
* setDocumentLocator} method. The application can use the
* object to obtain the location of any other SAX event
* in the XML source document.</p>
*
* <p>Note that the results returned by the object will be valid only
* during the scope of each callback method: the application
* will receive unpredictable results if it attempts to use the
* locator at any other time, or after parsing completes.</p>
*
* <p>SAX parsers are not required to supply a locator, but they are
* very strongly encouraged to do so. If the parser supplies a
* locator, it must do so before reporting any other document events.
* If no locator has been set by the time the application receives
* the {@link org.xml.sax.ContentHandler#startDocument startDocument}
* event, the application should assume that a locator is not
* available.</p>
*
* @since SAX 1.0
* @author David Megginson
* @see org.xml.sax.ContentHandler#setDocumentLocator
*/
public interface Locator {
/**
* Return the public identifier for the current document event.
*
* <p>The return value is the public identifier of the document
* entity or of the external parsed entity in which the markup
* triggering the event appears.</p>
*
* @return A string containing the public identifier, or
* null if none is available.
* @see #getSystemId
*/
public abstract String getPublicId ();
/**
* Return the system identifier for the current document event.
*
* <p>The return value is the system identifier of the document
* entity or of the external parsed entity in which the markup
* triggering the event appears.</p>
*
* <p>If the system identifier is a URL, the parser must resolve it
* fully before passing it to the application. For example, a file
* name must always be provided as a <em>file:...</em> URL, and other
* kinds of relative URI are also resolved against their bases.</p>
*
* @return A string containing the system identifier, or null
* if none is available.
* @see #getPublicId
*/
public abstract String getSystemId ();
/**
* Return the line number where the current document event ends.
* Lines are delimited by line ends, which are defined in
* the XML specification.
*
* <p><strong>Warning:</strong> The return value from the method
* is intended only as an approximation for the sake of diagnostics;
* it is not intended to provide sufficient information
* to edit the character content of the original XML document.
* In some cases, these "line" numbers match what would be displayed
* as columns, and in others they may not match the source text
* due to internal entity expansion. </p>
*
* <p>The return value is an approximation of the line number
* in the document entity or external parsed entity where the
* markup triggering the event appears.</p>
*
* <p>If possible, the SAX driver should provide the line position
* of the first character after the text associated with the document
* event. The first line is line 1.</p>
*
* @return The line number, or -1 if none is available.
* @see #getColumnNumber
*/
public abstract int getLineNumber ();
/**
* Return the column number where the current document event ends.
* This is one-based number of Java <code>char</code> values since
* the last line end.
*
* <p><strong>Warning:</strong> The return value from the method
* is intended only as an approximation for the sake of diagnostics;
* it is not intended to provide sufficient information
* to edit the character content of the original XML document.
* For example, when lines contain combining character sequences, wide
* characters, surrogate pairs, or bi-directional text, the value may
* not correspond to the column in a text editor's display. </p>
*
* <p>The return value is an approximation of the column number
* in the document entity or external parsed entity where the
* markup triggering the event appears.</p>
*
* <p>If possible, the SAX driver should provide the line position
* of the first character after the text associated with the document
* event. The first column in each line is column 1.</p>
*
* @return The column number, or -1 if none is available.
* @see #getLineNumber
*/
public abstract int getColumnNumber ();
}
// end of Locator.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAX exception class.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
// $Id: SAXException.java,v 1.3 2004/11/03 22:55:32 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Encapsulate a general SAX error or warning.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>This class can contain basic error or warning information from
* either the XML parser or the application: a parser writer or
* application writer can subclass it to provide additional
* functionality. SAX handlers may throw this exception or
* any exception subclassed from it.</p>
*
* <p>If the application needs to pass through other types of
* exceptions, it must wrap those exceptions in a SAXException
* or an exception derived from a SAXException.</p>
*
* <p>If the parser or application needs to include information about a
* specific location in an XML document, it should use the
* {@link org.xml.sax.SAXParseException SAXParseException} subclass.</p>
*
* @since SAX 1.0
* @author David Megginson
* @version 2.0.1 (sax2r2)
* @see org.xml.sax.SAXParseException
*/
public class SAXException extends Exception {
/**
* Create a new SAXException.
*/
public SAXException ()
{
super();
this.exception = null;
}
/**
* Create a new SAXException.
*
* @param message The error or warning message.
*/
public SAXException (String message) {
super(message);
this.exception = null;
}
/**
* Create a new SAXException wrapping an existing exception.
*
* <p>The existing exception will be embedded in the new
* one, and its message will become the default message for
* the SAXException.</p>
*
* @param e The exception to be wrapped in a SAXException.
*/
public SAXException (Exception e)
{
super();
this.exception = e;
}
/**
* Create a new SAXException from an existing exception.
*
* <p>The existing exception will be embedded in the new
* one, but the new exception will have its own message.</p>
*
* @param message The detail message.
* @param e The exception to be wrapped in a SAXException.
*/
public SAXException (String message, Exception e)
{
super(message);
this.exception = e;
}
/**
* Return a detail message for this exception.
*
* <p>If there is an embedded exception, and if the SAXException
* has no detail message of its own, this method will return
* the detail message from the embedded exception.</p>
*
* @return The error or warning message.
*/
public String getMessage ()
{
String message = super.getMessage();
if (message == null && exception != null) {
return exception.getMessage();
} else {
return message;
}
}
/**
* Return the embedded exception, if any.
*
* @return The embedded exception, or null if there is none.
*/
public Exception getException ()
{
return exception;
}
/**
* Return the cause of the exception
*
* @return Return the cause of the exception
*/
public Throwable getCause() {
return exception;
}
/**
* Override toString to pick up any embedded exception.
*
* @return A string representation of this exception.
*/
public String toString ()
{
if (exception != null) {
return super.toString() + "\n" + exception.toString();
} else {
return super.toString();
}
}
//////////////////////////////////////////////////////////////////////
// Internal state.
//////////////////////////////////////////////////////////////////////
/**
* @serial The embedded exception if tunnelling, or null.
*/
private Exception exception;
// Added serialVersionUID to preserve binary compatibility
static final long serialVersionUID = 583241635256073760L;
}
// end of SAXException.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAXNotRecognizedException.java - unrecognized feature or value.
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the Public Domain.
// $Id: SAXNotRecognizedException.java,v 1.3 2004/11/03 22:55:32 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Exception class for an unrecognized identifier.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>An XMLReader will throw this exception when it finds an
* unrecognized feature or property identifier; SAX applications and
* extensions may use this class for other, similar purposes.</p>
*
* @since SAX 2.0
* @author David Megginson
* @see org.xml.sax.SAXNotSupportedException
*/
public class SAXNotRecognizedException extends SAXException
{
/**
* Default constructor.
*/
public SAXNotRecognizedException ()
{
super();
}
/**
* Construct a new exception with the given message.
*
* @param message The text message of the exception.
*/
public SAXNotRecognizedException (String message)
{
super(message);
}
// Added serialVersionUID to preserve binary compatibility
static final long serialVersionUID = 5440506620509557213L;
}
// end of SAXNotRecognizedException.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAXNotSupportedException.java - unsupported feature or value.
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the Public Domain.
// $Id: SAXNotSupportedException.java,v 1.4 2004/11/03 22:55:32 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Exception class for an unsupported operation.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>An XMLReader will throw this exception when it recognizes a
* feature or property identifier, but cannot perform the requested
* operation (setting a state or value). Other SAX2 applications and
* extensions may use this class for similar purposes.</p>
*
* @since SAX 2.0
* @author David Megginson
* @see org.xml.sax.SAXNotRecognizedException
*/
public class SAXNotSupportedException extends SAXException
{
/**
* Construct a new exception with no message.
*/
public SAXNotSupportedException ()
{
super();
}
/**
* Construct a new exception with the given message.
*
* @param message The text message of the exception.
*/
public SAXNotSupportedException (String message)
{
super(message);
}
// Added serialVersionUID to preserve binary compatibility
static final long serialVersionUID = -1422818934641823846L;
}
// end of SAXNotSupportedException.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// SAX exception class.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
// $Id: SAXParseException.java,v 1.2 2004/11/03 22:55:32 jsuttor Exp $
package jdk.internal.org.xml.sax;
/**
* Encapsulate an XML parse error or warning.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>This exception may include information for locating the error
* in the original XML document, as if it came from a {@link Locator}
* object. Note that although the application
* will receive a SAXParseException as the argument to the handlers
* in the {@link org.xml.sax.ErrorHandler ErrorHandler} interface,
* the application is not actually required to throw the exception;
* instead, it can simply read the information in it and take a
* different action.</p>
*
* <p>Since this exception is a subclass of {@link org.xml.sax.SAXException
* SAXException}, it inherits the ability to wrap another exception.</p>
*
* @since SAX 1.0
* @author David Megginson
* @version 2.0.1 (sax2r2)
* @see org.xml.sax.SAXException
* @see org.xml.sax.Locator
* @see org.xml.sax.ErrorHandler
*/
public class SAXParseException extends SAXException {
//////////////////////////////////////////////////////////////////////
// Constructors.
//////////////////////////////////////////////////////////////////////
/**
* Create a new SAXParseException from a message and a Locator.
*
* <p>This constructor is especially useful when an application is
* creating its own exception from within a {@link org.xml.sax.ContentHandler
* ContentHandler} callback.</p>
*
* @param message The error or warning message.
* @param locator The locator object for the error or warning (may be
* null).
* @see org.xml.sax.Locator
*/
public SAXParseException (String message, Locator locator) {
super(message);
if (locator != null) {
init(locator.getPublicId(), locator.getSystemId(),
locator.getLineNumber(), locator.getColumnNumber());
} else {
init(null, null, -1, -1);
}
}
/**
* Wrap an existing exception in a SAXParseException.
*
* <p>This constructor is especially useful when an application is
* creating its own exception from within a {@link org.xml.sax.ContentHandler
* ContentHandler} callback, and needs to wrap an existing exception that is not a
* subclass of {@link org.xml.sax.SAXException SAXException}.</p>
*
* @param message The error or warning message, or null to
* use the message from the embedded exception.
* @param locator The locator object for the error or warning (may be
* null).
* @param e Any exception.
* @see org.xml.sax.Locator
*/
public SAXParseException (String message, Locator locator,
Exception e) {
super(message, e);
if (locator != null) {
init(locator.getPublicId(), locator.getSystemId(),
locator.getLineNumber(), locator.getColumnNumber());
} else {
init(null, null, -1, -1);
}
}
/**
* Create a new SAXParseException.
*
* <p>This constructor is most useful for parser writers.</p>
*
* <p>All parameters except the message are as if
* they were provided by a {@link Locator}. For example, if the
* system identifier is a URL (including relative filename), the
* caller must resolve it fully before creating the exception.</p>
*
*
* @param message The error or warning message.
* @param publicId The public identifier of the entity that generated
* the error or warning.
* @param systemId The system identifier of the entity that generated
* the error or warning.
* @param lineNumber The line number of the end of the text that
* caused the error or warning.
* @param columnNumber The column number of the end of the text that
* cause the error or warning.
*/
public SAXParseException (String message, String publicId, String systemId,
int lineNumber, int columnNumber)
{
super(message);
init(publicId, systemId, lineNumber, columnNumber);
}
/**
* Create a new SAXParseException with an embedded exception.
*
* <p>This constructor is most useful for parser writers who
* need to wrap an exception that is not a subclass of
* {@link org.xml.sax.SAXException SAXException}.</p>
*
* <p>All parameters except the message and exception are as if
* they were provided by a {@link Locator}. For example, if the
* system identifier is a URL (including relative filename), the
* caller must resolve it fully before creating the exception.</p>
*
* @param message The error or warning message, or null to use
* the message from the embedded exception.
* @param publicId The public identifier of the entity that generated
* the error or warning.
* @param systemId The system identifier of the entity that generated
* the error or warning.
* @param lineNumber The line number of the end of the text that
* caused the error or warning.
* @param columnNumber The column number of the end of the text that
* cause the error or warning.
* @param e Another exception to embed in this one.
*/
public SAXParseException (String message, String publicId, String systemId,
int lineNumber, int columnNumber, Exception e)
{
super(message, e);
init(publicId, systemId, lineNumber, columnNumber);
}
/**
* Internal initialization method.
*
* @param publicId The public identifier of the entity which generated the exception,
* or null.
* @param systemId The system identifier of the entity which generated the exception,
* or null.
* @param lineNumber The line number of the error, or -1.
* @param columnNumber The column number of the error, or -1.
*/
private void init (String publicId, String systemId,
int lineNumber, int columnNumber)
{
this.publicId = publicId;
this.systemId = systemId;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}
/**
* Get the public identifier of the entity where the exception occurred.
*
* @return A string containing the public identifier, or null
* if none is available.
* @see org.xml.sax.Locator#getPublicId
*/
public String getPublicId ()
{
return this.publicId;
}
/**
* Get the system identifier of the entity where the exception occurred.
*
* <p>If the system identifier is a URL, it will have been resolved
* fully.</p>
*
* @return A string containing the system identifier, or null
* if none is available.
* @see org.xml.sax.Locator#getSystemId
*/
public String getSystemId ()
{
return this.systemId;
}
/**
* The line number of the end of the text where the exception occurred.
*
* <p>The first line is line 1.</p>
*
* @return An integer representing the line number, or -1
* if none is available.
* @see org.xml.sax.Locator#getLineNumber
*/
public int getLineNumber ()
{
return this.lineNumber;
}
/**
* The column number of the end of the text where the exception occurred.
*
* <p>The first column in a line is position 1.</p>
*
* @return An integer representing the column number, or -1
* if none is available.
* @see org.xml.sax.Locator#getColumnNumber
*/
public int getColumnNumber ()
{
return this.columnNumber;
}
/**
* Override toString to provide more detailed error message.
*
* @return A string representation of this exception.
*/
public String toString() {
StringBuilder buf = new StringBuilder(getClass().getName());
String message = getLocalizedMessage();
if (publicId!=null) buf.append("publicId: ").append(publicId);
if (systemId!=null) buf.append("; systemId: ").append(systemId);
if (lineNumber!=-1) buf.append("; lineNumber: ").append(lineNumber);
if (columnNumber!=-1) buf.append("; columnNumber: ").append(columnNumber);
//append the exception message at the end
if (message!=null) buf.append("; ").append(message);
return buf.toString();
}
//////////////////////////////////////////////////////////////////////
// Internal state.
//////////////////////////////////////////////////////////////////////
/**
* @serial The public identifier, or null.
* @see #getPublicId
*/
private String publicId;
/**
* @serial The system identifier, or null.
* @see #getSystemId
*/
private String systemId;
/**
* @serial The line number, or -1.
* @see #getLineNumber
*/
private int lineNumber;
/**
* @serial The column number, or -1.
* @see #getColumnNumber
*/
private int columnNumber;
// Added serialVersionUID to preserve binary compatibility
static final long serialVersionUID = -5651165872476709336L;
}
// end of SAXParseException.java
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// XMLReader.java - read an XML document.
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the Public Domain.
// $Id: XMLReader.java,v 1.3 2004/11/03 22:55:32 jsuttor Exp $
package jdk.internal.org.xml.sax;
import java.io.IOException;
/**
* Interface for reading an XML document using callbacks.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p><strong>Note:</strong> despite its name, this interface does
* <em>not</em> extend the standard Java {@link java.io.Reader Reader}
* interface, because reading XML is a fundamentally different activity
* than reading character data.</p>
*
* <p>XMLReader is the interface that an XML parser's SAX2 driver must
* implement. This interface allows an application to set and
* query features and properties in the parser, to register
* event handlers for document processing, and to initiate
* a document parse.</p>
*
* <p>All SAX interfaces are assumed to be synchronous: the
* {@link #parse parse} methods must not return until parsing
* is complete, and readers must wait for an event-handler callback
* to return before reporting the next event.</p>
*
* <p>This interface replaces the (now deprecated) SAX 1.0 {@link
* org.xml.sax.Parser Parser} interface. The XMLReader interface
* contains two important enhancements over the old Parser
* interface (as well as some minor ones):</p>
*
* <ol>
* <li>it adds a standard way to query and set features and
* properties; and</li>
* <li>it adds Namespace support, which is required for many
* higher-level XML standards.</li>
* </ol>
*
* <p>There are adapters available to convert a SAX1 Parser to
* a SAX2 XMLReader and vice-versa.</p>
*
* @since SAX 2.0
* @author David Megginson
* @see org.xml.sax.XMLFilter
* @see org.xml.sax.helpers.ParserAdapter
* @see org.xml.sax.helpers.XMLReaderAdapter
*/
public interface XMLReader
{
////////////////////////////////////////////////////////////////////
// Configuration.
////////////////////////////////////////////////////////////////////
/**
* Look up the value of a feature flag.
*
* <p>The feature name is any fully-qualified URI. It is
* possible for an XMLReader to recognize a feature name but
* temporarily be unable to return its value.
* Some feature values may be available only in specific
* contexts, such as before, during, or after a parse.
* Also, some feature values may not be programmatically accessible.
* (In the case of an adapter for SAX1 {@link Parser}, there is no
* implementation-independent way to expose whether the underlying
* parser is performing validation, expanding external entities,
* and so forth.) </p>
*
* <p>All XMLReaders are required to recognize the
* http://xml.org/sax/features/namespaces and the
* http://xml.org/sax/features/namespace-prefixes feature names.</p>
*
* <p>Typical usage is something like this:</p>
*
* <pre>
* XMLReader r = new MySAXDriver();
*
* // try to activate validation
* try {
* r.setFeature("http://xml.org/sax/features/validation", true);
* } catch (SAXException e) {
* System.err.println("Cannot activate validation.");
* }
*
* // register event handlers
* r.setContentHandler(new MyContentHandler());
* r.setErrorHandler(new MyErrorHandler());
*
* // parse the first document
* try {
* r.parse("http://www.foo.com/mydoc.xml");
* } catch (IOException e) {
* System.err.println("I/O exception reading XML document");
* } catch (SAXException e) {
* System.err.println("XML exception reading document.");
* }
* </pre>
*
* <p>Implementors are free (and encouraged) to invent their own features,
* using names built on their own URIs.</p>
*
* @param name The feature name, which is a fully-qualified URI.
* @return The current value of the feature (true or false).
* @exception org.xml.sax.SAXNotRecognizedException If the feature
* value can't be assigned or retrieved.
* @exception org.xml.sax.SAXNotSupportedException When the
* XMLReader recognizes the feature name but
* cannot determine its value at this time.
* @see #setFeature
*/
public boolean getFeature (String name)
throws SAXNotRecognizedException, SAXNotSupportedException;
/**
* Set the value of a feature flag.
*
* <p>The feature name is any fully-qualified URI. It is
* possible for an XMLReader to expose a feature value but
* to be unable to change the current value.
* Some feature values may be immutable or mutable only
* in specific contexts, such as before, during, or after
* a parse.</p>
*
* <p>All XMLReaders are required to support setting
* http://xml.org/sax/features/namespaces to true and
* http://xml.org/sax/features/namespace-prefixes to false.</p>
*
* @param name The feature name, which is a fully-qualified URI.
* @param value The requested value of the feature (true or false).
* @exception org.xml.sax.SAXNotRecognizedException If the feature
* value can't be assigned or retrieved.
* @exception org.xml.sax.SAXNotSupportedException When the
* XMLReader recognizes the feature name but
* cannot set the requested value.
* @see #getFeature
*/
public void setFeature (String name, boolean value)
throws SAXNotRecognizedException, SAXNotSupportedException;
/**
* Look up the value of a property.
*
* <p>The property name is any fully-qualified URI. It is
* possible for an XMLReader to recognize a property name but
* temporarily be unable to return its value.
* Some property values may be available only in specific
* contexts, such as before, during, or after a parse.</p>
*
* <p>XMLReaders are not required to recognize any specific
* property names, though an initial core set is documented for
* SAX2.</p>
*
* <p>Implementors are free (and encouraged) to invent their own properties,
* using names built on their own URIs.</p>
*
* @param name The property name, which is a fully-qualified URI.
* @return The current value of the property.
* @exception org.xml.sax.SAXNotRecognizedException If the property
* value can't be assigned or retrieved.
* @exception org.xml.sax.SAXNotSupportedException When the
* XMLReader recognizes the property name but
* cannot determine its value at this time.
* @see #setProperty
*/
public Object getProperty (String name)
throws SAXNotRecognizedException, SAXNotSupportedException;
/**
* Set the value of a property.
*
* <p>The property name is any fully-qualified URI. It is
* possible for an XMLReader to recognize a property name but
* to be unable to change the current value.
* Some property values may be immutable or mutable only
* in specific contexts, such as before, during, or after
* a parse.</p>
*
* <p>XMLReaders are not required to recognize setting
* any specific property names, though a core set is defined by
* SAX2.</p>
*
* <p>This method is also the standard mechanism for setting
* extended handlers.</p>
*
* @param name The property name, which is a fully-qualified URI.
* @param value The requested value for the property.
* @exception org.xml.sax.SAXNotRecognizedException If the property
* value can't be assigned or retrieved.
* @exception org.xml.sax.SAXNotSupportedException When the
* XMLReader recognizes the property name but
* cannot set the requested value.
*/
public void setProperty (String name, Object value)
throws SAXNotRecognizedException, SAXNotSupportedException;
////////////////////////////////////////////////////////////////////
// Event handlers.
////////////////////////////////////////////////////////////////////
/**
* Allow an application to register an entity resolver.
*
* <p>If the application does not register an entity resolver,
* the XMLReader will perform its own default resolution.</p>
*
* <p>Applications may register a new or different resolver in the
* middle of a parse, and the SAX parser must begin using the new
* resolver immediately.</p>
*
* @param resolver The entity resolver.
* @see #getEntityResolver
*/
public void setEntityResolver (EntityResolver resolver);
/**
* Return the current entity resolver.
*
* @return The current entity resolver, or null if none
* has been registered.
* @see #setEntityResolver
*/
public EntityResolver getEntityResolver ();
/**
* Allow an application to register a DTD event handler.
*
* <p>If the application does not register a DTD handler, all DTD
* events reported by the SAX parser will be silently ignored.</p>
*
* <p>Applications may register a new or different handler in the
* middle of a parse, and the SAX parser must begin using the new
* handler immediately.</p>
*
* @param handler The DTD handler.
* @see #getDTDHandler
*/
public void setDTDHandler (DTDHandler handler);
/**
* Return the current DTD handler.
*
* @return The current DTD handler, or null if none
* has been registered.
* @see #setDTDHandler
*/
public DTDHandler getDTDHandler ();
/**
* Allow an application to register a content event handler.
*
* <p>If the application does not register a content handler, all
* content events reported by the SAX parser will be silently
* ignored.</p>
*
* <p>Applications may register a new or different handler in the
* middle of a parse, and the SAX parser must begin using the new
* handler immediately.</p>
*
* @param handler The content handler.
* @see #getContentHandler
*/
public void setContentHandler (ContentHandler handler);
/**
* Return the current content handler.
*
* @return The current content handler, or null if none
* has been registered.
* @see #setContentHandler
*/
public ContentHandler getContentHandler ();
/**
* Allow an application to register an error event handler.
*
* <p>If the application does not register an error handler, all
* error events reported by the SAX parser will be silently
* ignored; however, normal processing may not continue. It is
* highly recommended that all SAX applications implement an
* error handler to avoid unexpected bugs.</p>
*
* <p>Applications may register a new or different handler in the
* middle of a parse, and the SAX parser must begin using the new
* handler immediately.</p>
*
* @param handler The error handler.
* @see #getErrorHandler
*/
public void setErrorHandler (ErrorHandler handler);
/**
* Return the current error handler.
*
* @return The current error handler, or null if none
* has been registered.
* @see #setErrorHandler
*/
public ErrorHandler getErrorHandler ();
////////////////////////////////////////////////////////////////////
// Parsing.
////////////////////////////////////////////////////////////////////
/**
* Parse an XML document.
*
* <p>The application can use this method to instruct the XML
* reader to begin parsing an XML document from any valid input
* source (a character stream, a byte stream, or a URI).</p>
*
* <p>Applications may not invoke this method while a parse is in
* progress (they should create a new XMLReader instead for each
* nested XML document). Once a parse is complete, an
* application may reuse the same XMLReader object, possibly with a
* different input source.
* Configuration of the XMLReader object (such as handler bindings and
* values established for feature flags and properties) is unchanged
* by completion of a parse, unless the definition of that aspect of
* the configuration explicitly specifies other behavior.
* (For example, feature flags or properties exposing
* characteristics of the document being parsed.)
* </p>
*
* <p>During the parse, the XMLReader will provide information
* about the XML document through the registered event
* handlers.</p>
*
* <p>This method is synchronous: it will not return until parsing
* has ended. If a client application wants to terminate
* parsing early, it should throw an exception.</p>
*
* @param input The input source for the top-level of the
* XML document.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @exception java.io.IOException An IO exception from the parser,
* possibly from a byte stream or character stream
* supplied by the application.
* @see org.xml.sax.InputSource
* @see #parse(java.lang.String)
* @see #setEntityResolver
* @see #setDTDHandler
* @see #setContentHandler
* @see #setErrorHandler
*/
public void parse (InputSource input)
throws IOException, SAXException;
/**
* Parse an XML document from a system identifier (URI).
*
* <p>This method is a shortcut for the common case of reading a
* document from a system identifier. It is the exact
* equivalent of the following:</p>
*
* <pre>
* parse(new InputSource(systemId));
* </pre>
*
* <p>If the system identifier is a URL, it must be fully resolved
* by the application before it is passed to the parser.</p>
*
* @param systemId The system identifier (URI).
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @exception java.io.IOException An IO exception from the parser,
* possibly from a byte stream or character stream
* supplied by the application.
* @see #parse(org.xml.sax.InputSource)
*/
public void parse (String systemId)
throws IOException, SAXException;
}
/*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// DefaultHandler.java - default implementation of the core handlers.
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
// $Id: DefaultHandler.java,v 1.3 2006/04/13 02:06:32 jeffsuttor Exp $
package jdk.internal.org.xml.sax.helpers;
import java.io.IOException;
import jdk.internal.org.xml.sax.InputSource;
import jdk.internal.org.xml.sax.Locator;
import jdk.internal.org.xml.sax.Attributes;
import jdk.internal.org.xml.sax.EntityResolver;
import jdk.internal.org.xml.sax.DTDHandler;
import jdk.internal.org.xml.sax.ContentHandler;
import jdk.internal.org.xml.sax.ErrorHandler;
import jdk.internal.org.xml.sax.SAXException;
import jdk.internal.org.xml.sax.SAXParseException;
/**
* Default base class for SAX2 event handlers.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>This class is available as a convenience base class for SAX2
* applications: it provides default implementations for all of the
* callbacks in the four core SAX2 handler classes:</p>
*
* <ul>
* <li>{@link org.xml.sax.EntityResolver EntityResolver}</li>
* <li>{@link org.xml.sax.DTDHandler DTDHandler}</li>
* <li>{@link org.xml.sax.ContentHandler ContentHandler}</li>
* <li>{@link org.xml.sax.ErrorHandler ErrorHandler}</li>
* </ul>
*
* <p>Application writers can extend this class when they need to
* implement only part of an interface; parser writers can
* instantiate this class to provide default handlers when the
* application has not supplied its own.</p>
*
* <p>This class replaces the deprecated SAX1
* {@link org.xml.sax.HandlerBase HandlerBase} class.</p>
*
* @since SAX 2.0
* @author David Megginson,
* @see org.xml.sax.EntityResolver
* @see org.xml.sax.DTDHandler
* @see org.xml.sax.ContentHandler
* @see org.xml.sax.ErrorHandler
*/
public class DefaultHandler
implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler
{
////////////////////////////////////////////////////////////////////
// Default implementation of the EntityResolver interface.
////////////////////////////////////////////////////////////////////
/**
* Resolve an external entity.
*
* <p>Always return null, so that the parser will use the system
* identifier provided in the XML document. This method implements
* the SAX default behaviour: application writers can override it
* in a subclass to do special translations such as catalog lookups
* or URI redirection.</p>
*
* @param publicId The public identifier, or null if none is
* available.
* @param systemId The system identifier provided in the XML
* document.
* @return The new input source, or null to require the
* default behaviour.
* @exception java.io.IOException If there is an error setting
* up the new input source.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.EntityResolver#resolveEntity
*/
public InputSource resolveEntity (String publicId, String systemId)
throws IOException, SAXException
{
return null;
}
////////////////////////////////////////////////////////////////////
// Default implementation of DTDHandler interface.
////////////////////////////////////////////////////////////////////
/**
* Receive notification of a notation declaration.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass if they wish to keep track of the notations
* declared in a document.</p>
*
* @param name The notation name.
* @param publicId The notation public identifier, or null if not
* available.
* @param systemId The notation system identifier.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.DTDHandler#notationDecl
*/
public void notationDecl (String name, String publicId, String systemId)
throws SAXException
{
// no op
}
/**
* Receive notification of an unparsed entity declaration.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to keep track of the unparsed entities
* declared in a document.</p>
*
* @param name The entity name.
* @param publicId The entity public identifier, or null if not
* available.
* @param systemId The entity system identifier.
* @param notationName The name of the associated notation.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.DTDHandler#unparsedEntityDecl
*/
public void unparsedEntityDecl (String name, String publicId,
String systemId, String notationName)
throws SAXException
{
// no op
}
////////////////////////////////////////////////////////////////////
// Default implementation of ContentHandler interface.
////////////////////////////////////////////////////////////////////
/**
* Receive a Locator object for document events.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass if they wish to store the locator for use
* with other document events.</p>
*
* @param locator A locator for all SAX document events.
* @see org.xml.sax.ContentHandler#setDocumentLocator
* @see org.xml.sax.Locator
*/
public void setDocumentLocator (Locator locator)
{
// no op
}
/**
* Receive notification of the beginning of the document.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to take specific actions at the beginning
* of a document (such as allocating the root node of a tree or
* creating an output file).</p>
*
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#startDocument
*/
public void startDocument ()
throws SAXException
{
// no op
}
/**
* Receive notification of the end of the document.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to take specific actions at the end
* of a document (such as finalising a tree or closing an output
* file).</p>
*
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#endDocument
*/
public void endDocument ()
throws SAXException
{
// no op
}
/**
* Receive notification of the start of a Namespace mapping.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to take specific actions at the start of
* each Namespace prefix scope (such as storing the prefix mapping).</p>
*
* @param prefix The Namespace prefix being declared.
* @param uri The Namespace URI mapped to the prefix.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#startPrefixMapping
*/
public void startPrefixMapping (String prefix, String uri)
throws SAXException
{
// no op
}
/**
* Receive notification of the end of a Namespace mapping.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to take specific actions at the end of
* each prefix mapping.</p>
*
* @param prefix The Namespace prefix being declared.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#endPrefixMapping
*/
public void endPrefixMapping (String prefix)
throws SAXException
{
// no op
}
/**
* Receive notification of the start of an element.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to take specific actions at the start of
* each element (such as allocating a new tree node or writing
* output to a file).</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 attributes The attributes attached to the element. If
* there are no attributes, it shall be an empty
* Attributes object.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#startElement
*/
public void startElement (String uri, String localName,
String qName, Attributes attributes)
throws SAXException
{
// no op
}
/**
* Receive notification of the end of an element.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to take specific actions at the end of
* each element (such as finalising a tree node or writing
* output to a file).</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.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#endElement
*/
public void endElement (String uri, String localName, String qName)
throws SAXException
{
// no op
}
/**
* Receive notification of character data inside an element.
*
* <p>By default, do nothing. Application writers may override this
* method to take specific actions for each chunk of character data
* (such as adding the data to a node or buffer, or printing it to
* a file).</p>
*
* @param ch The characters.
* @param start The start position in the character array.
* @param length The number of characters to use from the
* character array.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#characters
*/
public void characters (char ch[], int start, int length)
throws SAXException
{
// no op
}
/**
* Receive notification of ignorable whitespace in element content.
*
* <p>By default, do nothing. Application writers may override this
* method to take specific actions for each chunk of ignorable
* whitespace (such as adding data to a node or buffer, or printing
* it to a file).</p>
*
* @param ch The whitespace characters.
* @param start The start position in the character array.
* @param length The number of characters to use from the
* character array.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#ignorableWhitespace
*/
public void ignorableWhitespace (char ch[], int start, int length)
throws SAXException
{
// no op
}
/**
* Receive notification of a processing instruction.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to take specific actions for each
* processing instruction, such as setting status variables or
* invoking other methods.</p>
*
* @param target The processing instruction target.
* @param data The processing instruction data, or null if
* none is supplied.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#processingInstruction
*/
public void processingInstruction (String target, String data)
throws SAXException
{
// no op
}
/**
* Receive notification of a skipped entity.
*
* <p>By default, do nothing. Application writers may override this
* method in a subclass to take specific actions for each
* processing instruction, such as setting status variables or
* invoking other methods.</p>
*
* @param name The name of the skipped entity.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ContentHandler#processingInstruction
*/
public void skippedEntity (String name)
throws SAXException
{
// no op
}
////////////////////////////////////////////////////////////////////
// Default implementation of the ErrorHandler interface.
////////////////////////////////////////////////////////////////////
/**
* Receive notification of a parser warning.
*
* <p>The default implementation does nothing. Application writers
* may override this method in a subclass to take specific actions
* for each warning, such as inserting the message in a log file or
* printing it to the console.</p>
*
* @param e The warning information encoded as an exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ErrorHandler#warning
* @see org.xml.sax.SAXParseException
*/
public void warning (SAXParseException e)
throws SAXException
{
// no op
}
/**
* Receive notification of a recoverable parser error.
*
* <p>The default implementation does nothing. Application writers
* may override this method in a subclass to take specific actions
* for each error, such as inserting the message in a log file or
* printing it to the console.</p>
*
* @param e The error information encoded as an exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ErrorHandler#warning
* @see org.xml.sax.SAXParseException
*/
public void error (SAXParseException e)
throws SAXException
{
// no op
}
/**
* Report a fatal XML parsing error.
*
* <p>The default implementation throws a SAXParseException.
* Application writers may override this method in a subclass if
* they need to take specific actions for each fatal error (such as
* collecting all of the errors into a single report): in any case,
* the application must stop all regular processing when this
* method is invoked, since the document is no longer reliable, and
* the parser may no longer report parsing events.</p>
*
* @param e The error information encoded as an exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
* @see org.xml.sax.ErrorHandler#fatalError
* @see org.xml.sax.SAXParseException
*/
public void fatalError (SAXParseException e)
throws SAXException
{
throw e;
}
}
// end of DefaultHandler.java
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml;
import java.io.*;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;
import jdk.internal.org.xml.sax.Attributes;
import jdk.internal.org.xml.sax.InputSource;
import jdk.internal.org.xml.sax.SAXException;
import jdk.internal.org.xml.sax.SAXParseException;
import jdk.internal.org.xml.sax.helpers.DefaultHandler;
import jdk.internal.util.xml.impl.SAXParserImpl;
import jdk.internal.util.xml.impl.XMLStreamWriterImpl;
/**
* A class used to aid in Properties load and save in XML. This class is
* re-implemented using a subset of SAX
*
* @author Joe Wang
* @since 8
*/
public class PropertiesDefaultHandler extends DefaultHandler {
// Elements specified in the properties.dtd
private static final String ELEMENT_ROOT = "properties";
private static final String ELEMENT_COMMENT = "comment";
private static final String ELEMENT_ENTRY = "entry";
private static final String ATTR_KEY = "key";
// The required DTD URI for exported properties
private static final String PROPS_DTD_DECL =
"<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">";
private static final String PROPS_DTD_URI =
"http://java.sun.com/dtd/properties.dtd";
private static final String PROPS_DTD =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<!-- DTD for properties -->"
+ "<!ELEMENT properties ( comment?, entry* ) >"
+ "<!ATTLIST properties"
+ " version CDATA #FIXED \"1.0\">"
+ "<!ELEMENT comment (#PCDATA) >"
+ "<!ELEMENT entry (#PCDATA) >"
+ "<!ATTLIST entry "
+ " key CDATA #REQUIRED>";
/**
* Version number for the format of exported properties files.
*/
private static final String EXTERNAL_XML_VERSION = "1.0";
private Properties properties;
public void load(Properties props, InputStream in)
throws IOException, InvalidPropertiesFormatException, UnsupportedEncodingException
{
this.properties = props;
try {
SAXParser parser = new SAXParserImpl();
parser.parse(in, this);
} catch (SAXException saxe) {
throw new InvalidPropertiesFormatException(saxe);
}
/**
* String xmlVersion = propertiesElement.getAttribute("version"); if
* (xmlVersion.compareTo(EXTERNAL_XML_VERSION) > 0) throw new
* InvalidPropertiesFormatException( "Exported Properties file format
* version " + xmlVersion + " is not supported. This java installation
* can read" + " versions " + EXTERNAL_XML_VERSION + " or older. You" +
* " may need to install a newer version of JDK.");
*/
}
public void store(Properties props, OutputStream os, String comment, String encoding)
throws IOException
{
try {
XMLStreamWriter writer = new XMLStreamWriterImpl(os, encoding);
writer.writeStartDocument();
writer.writeDTD(PROPS_DTD_DECL);
writer.writeStartElement(ELEMENT_ROOT);
if (comment != null && comment.length() > 0) {
writer.writeStartElement(ELEMENT_COMMENT);
writer.writeCharacters(comment);
writer.writeEndElement();
}
for (String key : props.stringPropertyNames()) {
String val = props.getProperty(key);
writer.writeStartElement(ELEMENT_ENTRY);
writer.writeAttribute(ATTR_KEY, key);
writer.writeCharacters(val);
writer.writeEndElement();
}
writer.writeEndElement();
writer.writeEndDocument();
writer.close();
} catch (XMLStreamException e) {
if (e.getCause() instanceof UnsupportedEncodingException) {
throw (UnsupportedEncodingException) e.getCause();
}
throw new IOException(e);
}
}
////////////////////////////////////////////////////////////////////
// Validate while parsing
////////////////////////////////////////////////////////////////////
final static String ALLOWED_ELEMENTS = "properties, comment, entry";
final static String ALLOWED_COMMENT = "comment";
////////////////////////////////////////////////////////////////////
// Handler methods
////////////////////////////////////////////////////////////////////
StringBuffer buf = new StringBuffer();
boolean sawComment = false;
boolean validEntry = false;
int rootElem = 0;
String key;
String rootElm;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException
{
if (rootElem < 2) {
rootElem++;
}
if (rootElm == null) {
fatalError(new SAXParseException("An XML properties document must contain"
+ " the DOCTYPE declaration as defined by java.util.Properties.", null));
}
if (rootElem == 1 && !rootElm.equals(qName)) {
fatalError(new SAXParseException("Document root element \"" + qName
+ "\", must match DOCTYPE root \"" + rootElm + "\"", null));
}
if (!ALLOWED_ELEMENTS.contains(qName)) {
fatalError(new SAXParseException("Element type \"" + qName + "\" must be declared.", null));
}
if (qName.equals(ELEMENT_ENTRY)) {
validEntry = true;
key = attributes.getValue(ATTR_KEY);
if (key == null) {
fatalError(new SAXParseException("Attribute \"key\" is required and must be specified for element type \"entry\"", null));
}
} else if (qName.equals(ALLOWED_COMMENT)) {
if (sawComment) {
fatalError(new SAXParseException("Only one comment element may be allowed. "
+ "The content of element type \"properties\" must match \"(comment?,entry*)\"", null));
}
sawComment = true;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (validEntry) {
buf.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (!ALLOWED_ELEMENTS.contains(qName)) {
fatalError(new SAXParseException("Element: " + qName + " is invalid, must match \"(comment?,entry*)\".", null));
}
if (validEntry) {
properties.setProperty(key, buf.toString());
buf.delete(0, buf.length());
validEntry = false;
}
}
@Override
public void notationDecl(String name, String publicId, String systemId) throws SAXException {
rootElm = name;
}
@Override
public InputSource resolveEntity(String pubid, String sysid)
throws SAXException, IOException {
{
if (sysid.equals(PROPS_DTD_URI)) {
InputSource is;
is = new InputSource(new StringReader(PROPS_DTD));
is.setSystemId(PROPS_DTD_URI);
return is;
}
throw new SAXException("Invalid system identifier: " + sysid);
}
}
@Override
public void error(SAXParseException x) throws SAXException {
throw x;
}
@Override
public void fatalError(SAXParseException x) throws SAXException {
throw x;
}
@Override
public void warning(SAXParseException x) throws SAXException {
throw x;
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import jdk.internal.org.xml.sax.InputSource;
import jdk.internal.org.xml.sax.SAXException;
import jdk.internal.org.xml.sax.XMLReader;
import jdk.internal.org.xml.sax.helpers.DefaultHandler;
/**
* Defines the API that wraps an {@link org.xml.sax.XMLReader}
* implementation class. In JAXP 1.0, this class wrapped the
* {@link org.xml.sax.Parser} interface, however this interface was
* replaced by the {@link org.xml.sax.XMLReader}. For ease
* of transition, this class continues to support the same name
* and interface as well as supporting new methods.
*
* An instance of this class can be obtained from the
* {@link javax.xml.parsers.SAXParserFactory#newSAXParser()} method.
* Once an instance of this class is obtained, XML can be parsed from
* a variety of input sources. These input sources are InputStreams,
* Files, URLs, and SAX InputSources.<p>
*
* This static method creates a new factory instance based
* on a system property setting or uses the platform default
* if no property has been defined.<p>
*
* The system property that controls which Factory implementation
* to create is named <code>&quot;javax.xml.parsers.SAXParserFactory&quot;</code>.
* This property names a class that is a concrete subclass of this
* abstract class. If no property is defined, a platform default
* will be used.</p>
*
* As the content is parsed by the underlying parser, methods of the
* given
* {@link org.xml.sax.helpers.DefaultHandler} are called.<p>
*
* Implementors of this class which wrap an underlaying implementation
* can consider using the {@link org.xml.sax.helpers.ParserAdapter}
* class to initially adapt their SAX1 implementation to work under
* this revised class.
*
* @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
* @version $Revision: 1.8 $, $Date: 2010-11-01 04:36:09 $
*
* @author Joe Wang
* This is a subset of that in JAXP, javax.xml.parsers.SAXParser
*
*/
public abstract class SAXParser {
/**
* <p>Protected constructor to prevent instantiation.</p>
*/
protected SAXParser() {
}
/**
* Parse the content of the given {@link java.io.InputStream}
* instance as XML using the specified
* {@link org.xml.sax.helpers.DefaultHandler}.
*
* @param is InputStream containing the content to be parsed.
* @param dh The SAX DefaultHandler to use.
*
* @throws IllegalArgumentException If the given InputStream is null.
* @throws IOException If any IO errors occur.
* @throws SAXException If any SAX errors occur during processing.
*
* @see org.xml.sax.DocumentHandler
*/
public void parse(InputStream is, DefaultHandler dh)
throws SAXException, IOException
{
if (is == null) {
throw new IllegalArgumentException("InputStream cannot be null");
}
InputSource input = new InputSource(is);
this.parse(input, dh);
}
/**
* Parse the content described by the giving Uniform Resource
* Identifier (URI) as XML using the specified
* {@link org.xml.sax.helpers.DefaultHandler}.
*
* @param uri The location of the content to be parsed.
* @param dh The SAX DefaultHandler to use.
*
* @throws IllegalArgumentException If the uri is null.
* @throws IOException If any IO errors occur.
* @throws SAXException If any SAX errors occur during processing.
*
* @see org.xml.sax.DocumentHandler
*/
public void parse(String uri, DefaultHandler dh)
throws SAXException, IOException
{
if (uri == null) {
throw new IllegalArgumentException("uri cannot be null");
}
InputSource input = new InputSource(uri);
this.parse(input, dh);
}
/**
* Parse the content of the file specified as XML using the
* specified {@link org.xml.sax.helpers.DefaultHandler}.
*
* @param f The file containing the XML to parse
* @param dh The SAX DefaultHandler to use.
*
* @throws IllegalArgumentException If the File object is null.
* @throws IOException If any IO errors occur.
* @throws SAXException If any SAX errors occur during processing.
*
* @see org.xml.sax.DocumentHandler
*/
public void parse(File f, DefaultHandler dh)
throws SAXException, IOException
{
if (f == null) {
throw new IllegalArgumentException("File cannot be null");
}
//convert file to appropriate URI, f.toURI().toASCIIString()
//converts the URI to string as per rule specified in
//RFC 2396,
InputSource input = new InputSource(f.toURI().toASCIIString());
this.parse(input, dh);
}
/**
* Parse the content given {@link org.xml.sax.InputSource}
* as XML using the specified
* {@link org.xml.sax.helpers.DefaultHandler}.
*
* @param is The InputSource containing the content to be parsed.
* @param dh The SAX DefaultHandler to use.
*
* @throws IllegalArgumentException If the <code>InputSource</code> object
* is <code>null</code>.
* @throws IOException If any IO errors occur.
* @throws SAXException If any SAX errors occur during processing.
*
* @see org.xml.sax.DocumentHandler
*/
public void parse(InputSource is, DefaultHandler dh)
throws SAXException, IOException
{
if (is == null) {
throw new IllegalArgumentException("InputSource cannot be null");
}
XMLReader reader = this.getXMLReader();
if (dh != null) {
reader.setContentHandler(dh);
reader.setEntityResolver(dh);
reader.setErrorHandler(dh);
reader.setDTDHandler(dh);
}
reader.parse(is);
}
/**
* Returns the {@link org.xml.sax.XMLReader} that is encapsulated by the
* implementation of this class.
*
* @return The XMLReader that is encapsulated by the
* implementation of this class.
*
* @throws SAXException If any SAX errors occur during processing.
*/
public abstract XMLReader getXMLReader() throws SAXException;
/**
* Indicates whether or not this parser is configured to
* understand namespaces.
*
* @return true if this parser is configured to
* understand namespaces; false otherwise.
*/
public abstract boolean isNamespaceAware();
/**
* Indicates whether or not this parser is configured to
* validate XML documents.
*
* @return true if this parser is configured to
* validate XML documents; false otherwise.
*/
public abstract boolean isValidating();
/**
* <p>Get the XInclude processing mode for this parser.</p>
*
* @return
* the return value of
* the {@link SAXParserFactory#isXIncludeAware()}
* when this parser was created from factory.
*
* @throws UnsupportedOperationException When implementation does not
* override this method
*
* @since 1.5
*
* @see SAXParserFactory#setXIncludeAware(boolean)
*/
public boolean isXIncludeAware() {
throw new UnsupportedOperationException(
"This parser does not support specification \""
+ this.getClass().getPackage().getSpecificationTitle()
+ "\" version \""
+ this.getClass().getPackage().getSpecificationVersion()
+ "\"");
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml;
/**
* A copy of the StAX XMLStreamException without Location support
*
* The base exception for unexpected processing errors. This Exception
* class is used to report well-formedness errors as well as unexpected
* processing conditions.
* @version 1.0
* @author Copyright (c) 2009 by Oracle Corporation. All Rights Reserved.
* @since 1.6
*/
public class XMLStreamException extends Exception {
private static final long serialVersionUID = 1L;
protected Throwable nested;
/**
* Default constructor
*/
public XMLStreamException() {
super();
}
/**
* Construct an exception with the assocated message.
*
* @param msg the message to report
*/
public XMLStreamException(String msg) {
super(msg);
}
/**
* Construct an exception with the assocated exception
*
* @param th a nested exception
*/
public XMLStreamException(Throwable th) {
super(th);
nested = th;
}
/**
* Construct an exception with the assocated message and exception
*
* @param th a nested exception
* @param msg the message to report
*/
public XMLStreamException(String msg, Throwable th) {
super(msg, th);
nested = th;
}
/**
* Gets the nested exception.
*
* @return Nested exception
*/
public Throwable getNestedException() {
return nested;
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml;
/**
* Basic XMLStreamWriter for writing simple XML files such as those
* defined in java.util.Properties
*
* This is a subset of javax.xml.stream.XMLStreamWriter
*
* @author Joe Wang
*/
public interface XMLStreamWriter {
//Defaults the XML version to 1.0, and the encoding to utf-8
public final static String DEFAULT_XML_VERSION = "1.0";
public final static String DEFAULT_ENCODING = "UTF-8";
/**
* Writes a start tag to the output. All writeStartElement methods
* open a new scope in the internal namespace context. Writing the
* corresponding EndElement causes the scope to be closed.
* @param localName local name of the tag, may not be null
* @throws XMLStreamException
*/
public void writeStartElement(String localName) throws XMLStreamException;
/**
* Writes an empty element tag to the output
* @param localName local name of the tag, may not be null
* @throws XMLStreamException
*/
public void writeEmptyElement(String localName) throws XMLStreamException;
/**
* Writes an end tag to the output relying on the internal
* state of the writer to determine the prefix and local name
* of the event.
* @throws XMLStreamException
*/
public void writeEndElement() throws XMLStreamException;
/**
* Closes any start tags and writes corresponding end tags.
* @throws XMLStreamException
*/
public void writeEndDocument() throws XMLStreamException;
/**
* Close this writer and free any resources associated with the
* writer. This must not close the underlying output stream.
* @throws XMLStreamException
*/
public void close() throws XMLStreamException;
/**
* Write any cached data to the underlying output mechanism.
* @throws XMLStreamException
*/
public void flush() throws XMLStreamException;
/**
* Writes an attribute to the output stream without
* a prefix.
* @param localName the local name of the attribute
* @param value the value of the attribute
* @throws IllegalStateException if the current state does not allow Attribute writing
* @throws XMLStreamException
*/
public void writeAttribute(String localName, String value)
throws XMLStreamException;
/**
* Writes a CData section
* @param data the data contained in the CData Section, may not be null
* @throws XMLStreamException
*/
public void writeCData(String data) throws XMLStreamException;
/**
* Write a DTD section. This string represents the entire doctypedecl production
* from the XML 1.0 specification.
*
* @param dtd the DTD to be written
* @throws XMLStreamException
*/
public void writeDTD(String dtd) throws XMLStreamException;
/**
* Write the XML Declaration. Defaults the XML version to 1.0, and the encoding to utf-8
* @throws XMLStreamException
*/
public void writeStartDocument() throws XMLStreamException;
/**
* Write the XML Declaration. Defaults the the encoding to utf-8
* @param version version of the xml document
* @throws XMLStreamException
*/
public void writeStartDocument(String version) throws XMLStreamException;
/**
* Write the XML Declaration. Note that the encoding parameter does
* not set the actual encoding of the underlying output. That must
* be set when the instance of the XMLStreamWriter is created using the
* XMLOutputFactory
* @param encoding encoding of the xml declaration
* @param version version of the xml document
* @throws XMLStreamException If given encoding does not match encoding
* of the underlying stream
*/
public void writeStartDocument(String encoding, String version)
throws XMLStreamException;
/**
* Write text to the output
* @param text the value to write
* @throws XMLStreamException
*/
public void writeCharacters(String text) throws XMLStreamException;
/**
* Write text to the output
* @param text the value to write
* @param start the starting position in the array
* @param len the number of characters to write
* @throws XMLStreamException
*/
public void writeCharacters(char[] text, int start, int len)
throws XMLStreamException;
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import jdk.internal.org.xml.sax.Attributes;
public class Attrs implements Attributes {
/**
* Attributes string array. Each individual attribute is represented by four
* strings: namespace URL(+0), qname(+1), local name(+2), value(+3),
* type(+4), declared["d"] and default["D"](+5). In order to find attribute
* by the attrubute index, the attribute index MUST be multiplied by 8. The
* result will point to the attribute namespace URL.
*/
/* pkg */ String[] mItems;
/**
* Number of attributes in the attributes string array.
*/
private char mLength;
/**
* current index
*/
private char mAttrIdx = 0;
/**
* Constructor.
*/
public Attrs() {
// The default number of attributies capacity is 8.
mItems = new String[(8 << 3)];
}
/**
* Sets up the number of attributes and ensure the capacity of the attribute
* string array.
*
* @param length The number of attributes in the object.
*/
public void setLength(char length) {
if (length > ((char) (mItems.length >> 3))) {
mItems = new String[length << 3];
}
mLength = length;
}
/**
* Return the number of attributes in the list.
*
* <p>Once you know the number of attributes, you can iterate through the
* list.</p>
*
* @return The number of attributes in the list.
* @see #getURI(int)
* @see #getLocalName(int)
* @see #getQName(int)
* @see #getType(int)
* @see #getValue(int)
*/
public int getLength() {
return mLength;
}
/**
* Look up an attribute's Namespace URI by index.
*
* @param index The attribute index (zero-based).
* @return The Namespace URI, or the empty string if none is available, or
* null if the index is out of range.
* @see #getLength
*/
public String getURI(int index) {
return ((index >= 0) && (index < mLength))
? (mItems[index << 3])
: null;
}
/**
* Look up an attribute's local name by index.
*
* @param index The attribute index (zero-based).
* @return The local name, or the empty string if Namespace processing is
* not being performed, or null if the index is out of range.
* @see #getLength
*/
public String getLocalName(int index) {
return ((index >= 0) && (index < mLength))
? (mItems[(index << 3) + 2])
: null;
}
/**
* Look up an attribute's XML 1.0 qualified name by index.
*
* @param index The attribute index (zero-based).
* @return The XML 1.0 qualified name, or the empty string if none is
* available, or null if the index is out of range.
* @see #getLength
*/
public String getQName(int index) {
if ((index < 0) || (index >= mLength)) {
return null;
}
return mItems[(index << 3) + 1];
}
/**
* Look up an attribute's type by index.
*
* <p>The attribute type is one of the strings "CDATA", "ID", "IDREF",
* "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", or "NOTATION"
* (always in upper case).</p>
*
* <p>If the parser has not read a declaration for the attribute, or if the
* parser does not report attribute types, then it must return the value
* "CDATA" as stated in the XML 1.0 Recommentation (clause 3.3.3,
* "Attribute-Value Normalization").</p>
*
* <p>For an enumerated attribute that is not a notation, the parser will
* report the type as "NMTOKEN".</p>
*
* @param index The attribute index (zero-based).
* @return The attribute's type as a string, or null if the index is out of
* range.
* @see #getLength
*/
public String getType(int index) {
return ((index >= 0) && (index < (mItems.length >> 3)))
? (mItems[(index << 3) + 4])
: null;
}
/**
* Look up an attribute's value by index.
*
* <p>If the attribute value is a list of tokens (IDREFS, ENTITIES, or
* NMTOKENS), the tokens will be concatenated into a single string with each
* token separated by a single space.</p>
*
* @param index The attribute index (zero-based).
* @return The attribute's value as a string, or null if the index is out of
* range.
* @see #getLength
*/
public String getValue(int index) {
return ((index >= 0) && (index < mLength))
? (mItems[(index << 3) + 3])
: null;
}
/**
* Look up the index of an attribute by Namespace name.
*
* @param uri The Namespace URI, or the empty string if the name has no
* Namespace URI.
* @param localName The attribute's local name.
* @return The index of the attribute, or -1 if it does not appear in the
* list.
*/
public int getIndex(String uri, String localName) {
char len = mLength;
for (char idx = 0; idx < len; idx++) {
if ((mItems[idx << 3]).equals(uri)
&& mItems[(idx << 3) + 2].equals(localName)) {
return idx;
}
}
return -1;
}
/**
* Look up the index of an attribute by Namespace name.
*
* @param uri The Namespace URI, or the empty string if the name has no
* Namespace URI. <code>null</code> value enforce the search by the local
* name only.
* @param localName The attribute's local name.
* @return The index of the attribute, or -1 if it does not appear in the
* list.
*/
/* pkg */ int getIndexNullNS(String uri, String localName) {
char len = mLength;
if (uri != null) {
for (char idx = 0; idx < len; idx++) {
if ((mItems[idx << 3]).equals(uri)
&& mItems[(idx << 3) + 2].equals(localName)) {
return idx;
}
}
} else {
for (char idx = 0; idx < len; idx++) {
if (mItems[(idx << 3) + 2].equals(localName)) {
return idx;
}
}
}
return -1;
}
/**
* Look up the index of an attribute by XML 1.0 qualified name.
*
* @param qName The qualified (prefixed) name.
* @return The index of the attribute, or -1 if it does not appear in the
* list.
*/
public int getIndex(String qName) {
char len = mLength;
for (char idx = 0; idx < len; idx++) {
if (mItems[(idx << 3) + 1].equals(qName)) {
return idx;
}
}
return -1;
}
/**
* Look up an attribute's type by Namespace name.
*
* <p>See {@link #getType(int) getType(int)} for a description of the
* possible types.</p>
*
* @param uri The Namespace URI, or the empty String if the name has no
* Namespace URI.
* @param localName The local name of the attribute.
* @return The attribute type as a string, or null if the attribute is not
* in the list or if Namespace processing is not being performed.
*/
public String getType(String uri, String localName) {
int idx = getIndex(uri, localName);
return (idx >= 0) ? (mItems[(idx << 3) + 4]) : null;
}
/**
* Look up an attribute's type by XML 1.0 qualified name.
*
* <p>See {@link #getType(int) getType(int)} for a description of the
* possible types.</p>
*
* @param qName The XML 1.0 qualified name.
* @return The attribute type as a string, or null if the attribute is not
* in the list or if qualified names are not available.
*/
public String getType(String qName) {
int idx = getIndex(qName);
return (idx >= 0) ? (mItems[(idx << 3) + 4]) : null;
}
/**
* Look up an attribute's value by Namespace name.
*
* <p>See {@link #getValue(int) getValue(int)} for a description of the
* possible values.</p>
*
* @param uri The Namespace URI, or the empty String if the name has no
* Namespace URI.
* @param localName The local name of the attribute.
* @return The attribute value as a string, or null if the attribute is not
* in the list.
*/
public String getValue(String uri, String localName) {
int idx = getIndex(uri, localName);
return (idx >= 0) ? (mItems[(idx << 3) + 3]) : null;
}
/**
* Look up an attribute's value by XML 1.0 qualified name.
*
* <p>See {@link #getValue(int) getValue(int)} for a description of the
* possible values.</p>
*
* @param qName The XML 1.0 qualified name.
* @return The attribute value as a string, or null if the attribute is not
* in the list or if qualified names are not available.
*/
public String getValue(String qName) {
int idx = getIndex(qName);
return (idx >= 0) ? (mItems[(idx << 3) + 3]) : null;
}
/**
* Returns false unless the attribute was declared in the DTD. This helps
* distinguish two kinds of attributes that SAX reports as CDATA: ones that
* were declared (and hence are usually valid), and those that were not (and
* which are never valid).
*
* @param index The attribute index (zero-based).
* @return true if the attribute was declared in the DTD, false otherwise.
* @exception java.lang.ArrayIndexOutOfBoundsException When the supplied
* index does not identify an attribute.
*/
public boolean isDeclared(int index) {
if ((index < 0) || (index >= mLength)) {
throw new ArrayIndexOutOfBoundsException("");
}
return ((mItems[(index << 3) + 5]) != null);
}
/**
* Returns false unless the attribute was declared in the DTD. This helps
* distinguish two kinds of attributes that SAX reports as CDATA: ones that
* were declared (and hence are usually valid), and those that were not (and
* which are never valid).
*
* @param qName The XML qualified (prefixed) name.
* @return true if the attribute was declared in the DTD, false otherwise.
* @exception java.lang.IllegalArgumentException When the supplied name does
* not identify an attribute.
*/
public boolean isDeclared(String qName) {
int idx = getIndex(qName);
if (idx < 0) {
throw new IllegalArgumentException("");
}
return ((mItems[(idx << 3) + 5]) != null);
}
/**
* Returns false unless the attribute was declared in the DTD. This helps
* distinguish two kinds of attributes that SAX reports as CDATA: ones that
* were declared (and hence are usually valid), and those that were not (and
* which are never valid).
*
* <p>Remember that since DTDs do not "understand" namespaces, the namespace
* URI associated with an attribute may not have come from the DTD. The
* declaration will have applied to the attribute's <em>qName</em>.
*
* @param uri The Namespace URI, or the empty string if the name has no
* Namespace URI.
* @param localName The attribute's local name.
* @return true if the attribute was declared in the DTD, false otherwise.
* @exception java.lang.IllegalArgumentException When the supplied names do
* not identify an attribute.
*/
public boolean isDeclared(String uri, String localName) {
int idx = getIndex(uri, localName);
if (idx < 0) {
throw new IllegalArgumentException("");
}
return ((mItems[(idx << 3) + 5]) != null);
}
/**
* Returns true unless the attribute value was provided by DTD defaulting.
*
* @param index The attribute index (zero-based).
* @return true if the value was found in the XML text, false if the value
* was provided by DTD defaulting.
* @exception java.lang.ArrayIndexOutOfBoundsException When the supplied
* index does not identify an attribute.
*/
public boolean isSpecified(int index) {
if ((index < 0) || (index >= mLength)) {
throw new ArrayIndexOutOfBoundsException("");
}
String str = mItems[(index << 3) + 5];
return ((str != null) ? (str.charAt(0) == 'd') : true);
}
/**
* Returns true unless the attribute value was provided by DTD defaulting.
*
* <p>Remember that since DTDs do not "understand" namespaces, the namespace
* URI associated with an attribute may not have come from the DTD. The
* declaration will have applied to the attribute's <em>qName</em>.
*
* @param uri The Namespace URI, or the empty string if the name has no
* Namespace URI.
* @param localName The attribute's local name.
* @return true if the value was found in the XML text, false if the value
* was provided by DTD defaulting.
* @exception java.lang.IllegalArgumentException When the supplied names do
* not identify an attribute.
*/
public boolean isSpecified(String uri, String localName) {
int idx = getIndex(uri, localName);
if (idx < 0) {
throw new IllegalArgumentException("");
}
String str = mItems[(idx << 3) + 5];
return ((str != null) ? (str.charAt(0) == 'd') : true);
}
/**
* Returns true unless the attribute value was provided by DTD defaulting.
*
* @param qName The XML qualified (prefixed) name.
* @return true if the value was found in the XML text, false if the value
* was provided by DTD defaulting.
* @exception java.lang.IllegalArgumentException When the supplied name does
* not identify an attribute.
*/
public boolean isSpecified(String qName) {
int idx = getIndex(qName);
if (idx < 0) {
throw new IllegalArgumentException("");
}
String str = mItems[(idx << 3) + 5];
return ((str != null) ? (str.charAt(0) == 'd') : true);
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import java.io.Reader;
/**
* A parsed entity input state.
*
* This class represents a parsed entity input state. The parser uses
* an instance of this class to manage input.
*/
public class Input {
/** The entity public identifier or null. */
public String pubid;
/** The entity systen identifier or null. */
public String sysid;
/** The encoding from XML declaration or null */
public String xmlenc;
/** The XML version from XML declaration or 0x0000 */
public char xmlver;
/** The entity reader. */
public Reader src;
/** The character buffer. */
public char[] chars;
/** The length of the character buffer. */
public int chLen;
/** The index of the next character to read. */
public int chIdx;
/** The next input in a chain. */
public Input next;
/**
* Constructor.
*
* @param buffsize The input buffer size.
*/
public Input(int buffsize) {
chars = new char[buffsize];
chLen = chars.length;
}
/**
* Constructor.
*
* @param buff The input buffer.
*/
public Input(char[] buff) {
chars = buff;
chLen = chars.length;
}
/**
* Constructor.
*/
public Input() {
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
/**
* A name with value pair.
*
* This class keeps name with value pair with additional information and
* supports pair chaining.
*/
public class Pair {
/** The pair name. */
public String name;
/** The pair value. */
public String value;
/** The pair numeric value. */
public int num;
/** The characters of name. */
public char[] chars;
/** The pair identifier. */
public int id;
/** The list of associated pairs. */
public Pair list;
/** The next pair in a chain. */
public Pair next;
/**
* Creates a qualified name string from qualified name.
*
* @return The qualified name string.
*/
public String qname() {
return new String(chars, 1, chars.length - 1);
}
/**
* Creates a local name string from qualified name.
*
* @return The local name string.
*/
public String local() {
if (chars[0] != 0) {
return new String(chars, chars[0] + 1, chars.length - chars[0] - 1);
}
return new String(chars, 1, chars.length - 1);
}
/**
* Creates a prefix string from qualified name.
*
* @return The prefix string.
*/
public String pref() {
if (chars[0] != 0) {
return new String(chars, 1, chars[0] - 1);
}
return "";
}
/**
* Compares two qualified name prefixes.
*
* @param qname A qualified name.
* @return true if prefixes are equal.
*/
public boolean eqpref(char[] qname) {
if (chars[0] == qname[0]) {
char len = chars[0];
for (char i = 1; i < len; i += 1) {
if (chars[i] != qname[i]) {
return false;
}
}
return true;
}
return false;
}
/**
* Compares two qualified names.
*
* @param qname A qualified name.
* @return true if qualified names are equal.
*/
public boolean eqname(char[] qname) {
char len = (char) chars.length;
if (len == qname.length) {
for (char i = 0; i < len; i += 1) {
if (chars[i] != qname[i]) {
return false;
}
}
return true;
}
return false;
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import jdk.internal.org.xml.sax.InputSource;
import jdk.internal.org.xml.sax.SAXException;
/**
* XML non-validating parser engine.
*/
public abstract class Parser {
public final static String FAULT = "";
protected final static int BUFFSIZE_READER = 512;
protected final static int BUFFSIZE_PARSER = 128;
/**
* The end of stream character.
*/
public final static char EOS = 0xffff;
private Pair mNoNS; // there is no namespace
private Pair mXml; // the xml namespace
private Map<String, Input> mEnt; // the entities look up table
private Map<String, Input> mPEnt; // the parmeter entities look up table
protected boolean mIsSAlone; // xml decl standalone flag
protected boolean mIsSAloneSet; // standalone is explicitely set
protected boolean mIsNSAware; // if true - namespace aware mode
protected int mPh; // current phase of document processing
protected final static int PH_BEFORE_DOC = -1; // before parsing
protected final static int PH_DOC_START = 0; // document start
protected final static int PH_MISC_DTD = 1; // misc before DTD
protected final static int PH_DTD = 2; // DTD
protected final static int PH_DTD_MISC = 3; // misc after DTD
protected final static int PH_DOCELM = 4; // document's element
protected final static int PH_DOCELM_MISC = 5; // misc after element
protected final static int PH_AFTER_DOC = 6; // after parsing
protected int mEvt; // current event type
protected final static int EV_NULL = 0; // unknown
protected final static int EV_ELM = 1; // empty element
protected final static int EV_ELMS = 2; // start element
protected final static int EV_ELME = 3; // end element
protected final static int EV_TEXT = 4; // textual content
protected final static int EV_WSPC = 5; // white space content
protected final static int EV_PI = 6; // processing instruction
protected final static int EV_CDAT = 7; // character data
protected final static int EV_COMM = 8; // comment
protected final static int EV_DTD = 9; // document type definition
protected final static int EV_ENT = 10; // skipped entity
private char mESt; // built-in entity recognizer state
// mESt values:
// 0x100 : the initial state
// > 0x100 : unrecognized name
// < 0x100 : replacement character
protected char[] mBuff; // parser buffer
protected int mBuffIdx; // index of the last char
protected Pair mPref; // stack of prefixes
protected Pair mElm; // stack of elements
// mAttL.chars - element qname
// mAttL.next - next element
// mAttL.list - list of attributes defined on this element
// mAttL.list.chars - attribute qname
// mAttL.list.id - a char representing attribute's type see below
// mAttL.list.next - next attribute defined on the element
// mAttL.list.list - devault value structure or null
// mAttL.list.list.chars - "name='value' " chars array for Input
//
// Attribute type character values:
// 'i' - "ID"
// 'r' - "IDREF"
// 'R' - "IDREFS"
// 'n' - "ENTITY"
// 'N' - "ENTITIES"
// 't' - "NMTOKEN"
// 'T' - "NMTOKENS"
// 'u' - enumeration type
// 'o' - "NOTATION"
// 'c' - "CDATA"
// see also: bkeyword() and atype()
//
protected Pair mAttL; // list of defined attrs by element name
protected Input mDoc; // document entity
protected Input mInp; // stack of entities
private char[] mChars; // reading buffer
private int mChLen; // current capacity
private int mChIdx; // index to the next char
protected Attrs mAttrs; // attributes of the curr. element
private String[] mItems; // attributes array of the curr. element
private char mAttrIdx; // attributes counter/index
private String mUnent; // unresolved entity name
private Pair mDltd; // deleted objects for reuse
/**
* Default prefixes
*/
private final static char NONS[];
private final static char XML[];
private final static char XMLNS[];
static {
NONS = new char[1];
NONS[0] = (char) 0;
XML = new char[4];
XML[0] = (char) 4;
XML[1] = 'x';
XML[2] = 'm';
XML[3] = 'l';
XMLNS = new char[6];
XMLNS[0] = (char) 6;
XMLNS[1] = 'x';
XMLNS[2] = 'm';
XMLNS[3] = 'l';
XMLNS[4] = 'n';
XMLNS[5] = 's';
}
/**
* ASCII character type array.
*
* This array maps an ASCII (7 bit) character to the character type.<br />
* Possible character type values are:<br /> - ' ' for any kind of white
* space character;<br /> - 'a' for any lower case alphabetical character
* value;<br /> - 'A' for any upper case alphabetical character value;<br />
* - 'd' for any decimal digit character value;<br /> - 'z' for any
* character less then ' ' except '\t', '\n', '\r';<br /> An ASCII (7 bit)
* character which does not fall in any category listed above is mapped to
* it self.
*/
private static final byte asctyp[];
/**
* NMTOKEN character type array.
*
* This array maps an ASCII (7 bit) character to the character type.<br />
* Possible character type values are:<br /> - 0 for underscore ('_') or any
* lower and upper case alphabetical character value;<br /> - 1 for colon
* (':') character;<br /> - 2 for dash ('-') and dot ('.') or any decimal
* digit character value;<br /> - 3 for any kind of white space character<br
* /> An ASCII (7 bit) character which does not fall in any category listed
* above is mapped to 0xff.
*/
private static final byte nmttyp[];
/**
* Static constructor.
*
* Sets up the ASCII character type array which is used by
* {@link #asctyp asctyp} method and NMTOKEN character type array.
*/
static {
short i = 0;
asctyp = new byte[0x80];
while (i < ' ') {
asctyp[i++] = (byte) 'z';
}
asctyp['\t'] = (byte) ' ';
asctyp['\r'] = (byte) ' ';
asctyp['\n'] = (byte) ' ';
while (i < '0') {
asctyp[i] = (byte) i++;
}
while (i <= '9') {
asctyp[i++] = (byte) 'd';
}
while (i < 'A') {
asctyp[i] = (byte) i++;
}
while (i <= 'Z') {
asctyp[i++] = (byte) 'A';
}
while (i < 'a') {
asctyp[i] = (byte) i++;
}
while (i <= 'z') {
asctyp[i++] = (byte) 'a';
}
while (i < 0x80) {
asctyp[i] = (byte) i++;
}
nmttyp = new byte[0x80];
for (i = 0; i < '0'; i++) {
nmttyp[i] = (byte) 0xff;
}
while (i <= '9') {
nmttyp[i++] = (byte) 2; // digits
}
while (i < 'A') {
nmttyp[i++] = (byte) 0xff;
}
// skiped upper case alphabetical character are already 0
for (i = '['; i < 'a'; i++) {
nmttyp[i] = (byte) 0xff;
}
// skiped lower case alphabetical character are already 0
for (i = '{'; i < 0x80; i++) {
nmttyp[i] = (byte) 0xff;
}
nmttyp['_'] = 0;
nmttyp[':'] = 1;
nmttyp['.'] = 2;
nmttyp['-'] = 2;
nmttyp[' '] = 3;
nmttyp['\t'] = 3;
nmttyp['\r'] = 3;
nmttyp['\n'] = 3;
}
/**
* Constructor.
*/
protected Parser() {
mPh = PH_BEFORE_DOC; // before parsing
// Initialize the parser
mBuff = new char[BUFFSIZE_PARSER];
mAttrs = new Attrs();
// Default namespace
mPref = pair(mPref);
mPref.name = "";
mPref.value = "";
mPref.chars = NONS;
mNoNS = mPref; // no namespace
// XML namespace
mPref = pair(mPref);
mPref.name = "xml";
mPref.value = "http://www.w3.org/XML/1998/namespace";
mPref.chars = XML;
mXml = mPref; // XML namespace
}
/**
* Initializes parser's internals. Note, current input has to be set before
* this method is called.
*/
protected void init() {
mUnent = null;
mElm = null;
mPref = mXml;
mAttL = null;
mPEnt = new HashMap<>();
mEnt = new HashMap<>();
mDoc = mInp; // current input is document entity
mChars = mInp.chars; // use document entity buffer
mPh = PH_DOC_START; // the begining of the document
}
/**
* Cleans up parser internal resources.
*/
protected void cleanup() {
// Default attributes
while (mAttL != null) {
while (mAttL.list != null) {
if (mAttL.list.list != null) {
del(mAttL.list.list);
}
mAttL.list = del(mAttL.list);
}
mAttL = del(mAttL);
}
// Element stack
while (mElm != null) {
mElm = del(mElm);
}
// Namespace prefixes
while (mPref != mXml) {
mPref = del(mPref);
}
// Inputs
while (mInp != null) {
pop();
}
// Document reader
if ((mDoc != null) && (mDoc.src != null)) {
try {
mDoc.src.close();
} catch (IOException ioe) {
}
}
mPEnt = null;
mEnt = null;
mDoc = null;
mPh = PH_AFTER_DOC; // before documnet processing
}
/**
* Processes a portion of document. This method returns one of EV_*
* constants as an identifier of the portion of document have been read.
*
* @return Identifier of processed document portion.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
protected int step() throws Exception {
mEvt = EV_NULL;
int st = 0;
while (mEvt == EV_NULL) {
char ch = (mChIdx < mChLen) ? mChars[mChIdx++] : getch();
switch (st) {
case 0: // all sorts of markup (dispetcher)
if (ch != '<') {
bkch();
mBuffIdx = -1; // clean parser buffer
st = 1;
break;
}
switch (getch()) {
case '/': // the end of the element content
mEvt = EV_ELME;
if (mElm == null) {
panic(FAULT);
}
// Check element's open/close tags balance
mBuffIdx = -1; // clean parser buffer
bname(mIsNSAware);
char[] chars = mElm.chars;
if (chars.length == (mBuffIdx + 1)) {
for (char i = 1; i <= mBuffIdx; i += 1) {
if (chars[i] != mBuff[i]) {
panic(FAULT);
}
}
} else {
panic(FAULT);
}
// Skip white spaces before '>'
if (wsskip() != '>') {
panic(FAULT);
}
getch(); // read '>'
break;
case '!': // a comment or a CDATA
ch = getch();
bkch();
switch (ch) {
case '-': // must be a comment
mEvt = EV_COMM;
comm();
break;
case '[': // must be a CDATA section
mEvt = EV_CDAT;
cdat();
break;
default: // must be 'DOCTYPE'
mEvt = EV_DTD;
dtd();
break;
}
break;
case '?': // processing instruction
mEvt = EV_PI;
pi();
break;
default: // must be the first char of an xml name
bkch();
// Read an element name and put it on top of the
// element stack
mElm = pair(mElm); // add new element to the stack
mElm.chars = qname(mIsNSAware);
mElm.name = mElm.local();
mElm.id = (mElm.next != null) ? mElm.next.id : 0; // flags
mElm.num = 0; // namespace counter
// Find the list of defined attributs of the current
// element
Pair elm = find(mAttL, mElm.chars);
mElm.list = (elm != null) ? elm.list : null;
// Read attributes till the end of the element tag
mAttrIdx = 0;
Pair att = pair(null);
att.num = 0; // clear attribute's flags
attr(att); // get all attributes inc. defaults
del(att);
mElm.value = (mIsNSAware) ? rslv(mElm.chars) : null;
// Skip white spaces before '>'
switch (wsskip()) {
case '>':
getch(); // read '>'
mEvt = EV_ELMS;
break;
case '/':
getch(); // read '/'
if (getch() != '>') // read '>'
{
panic(FAULT);
}
mEvt = EV_ELM;
break;
default:
panic(FAULT);
}
break;
}
break;
case 1: // read white space
switch (ch) {
case ' ':
case '\t':
case '\n':
bappend(ch);
break;
case '\r': // EOL processing [#2.11]
if (getch() != '\n') {
bkch();
}
bappend('\n');
break;
case '<':
mEvt = EV_WSPC;
bkch();
bflash_ws();
break;
default:
bkch();
st = 2;
break;
}
break;
case 2: // read the text content of the element
switch (ch) {
case '&':
if (mUnent == null) {
// There was no unresolved entity on previous step.
if ((mUnent = ent('x')) != null) {
mEvt = EV_TEXT;
bkch(); // move back to ';' after entity name
setch('&'); // parser must be back on next step
bflash();
}
} else {
// There was unresolved entity on previous step.
mEvt = EV_ENT;
skippedEnt(mUnent);
mUnent = null;
}
break;
case '<':
mEvt = EV_TEXT;
bkch();
bflash();
break;
case '\r': // EOL processing [#2.11]
if (getch() != '\n') {
bkch();
}
bappend('\n');
break;
case EOS:
panic(FAULT);
default:
bappend(ch);
break;
}
break;
default:
panic(FAULT);
}
}
return mEvt;
}
/**
* Parses the document type declaration.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private void dtd() throws Exception {
char ch;
String str = null;
String name = null;
Pair psid = null;
// read 'DOCTYPE'
if ("DOCTYPE".equals(name(false)) != true) {
panic(FAULT);
}
mPh = PH_DTD; // DTD
for (short st = 0; st >= 0;) {
ch = getch();
switch (st) {
case 0: // read the document type name
if (chtyp(ch) != ' ') {
bkch();
name = name(mIsNSAware);
wsskip();
st = 1; // read 'PUPLIC' or 'SYSTEM'
}
break;
case 1: // read 'PUPLIC' or 'SYSTEM'
switch (chtyp(ch)) {
case 'A':
bkch();
psid = pubsys(' ');
st = 2; // skip spaces before internal subset
docType(name, psid.name, psid.value);
break;
case '[':
bkch();
st = 2; // skip spaces before internal subset
docType(name, null, null);
break;
case '>':
bkch();
st = 3; // skip spaces after internal subset
docType(name, null, null);
break;
default:
panic(FAULT);
}
break;
case 2: // skip spaces before internal subset
switch (chtyp(ch)) {
case '[':
// Process internal subset
dtdsub();
st = 3; // skip spaces after internal subset
break;
case '>':
// There is no internal subset
bkch();
st = 3; // skip spaces after internal subset
break;
case ' ':
// skip white spaces
break;
default:
panic(FAULT);
}
break;
case 3: // skip spaces after internal subset
switch (chtyp(ch)) {
case '>':
if (psid != null) {
// Report the DTD external subset
InputSource is = resolveEnt(name, psid.name, psid.value);
if (is != null) {
if (mIsSAlone == false) {
// Set the end of DTD external subset char
bkch();
setch(']');
// Set the DTD external subset InputSource
push(new Input(BUFFSIZE_READER));
setinp(is);
mInp.pubid = psid.name;
mInp.sysid = psid.value;
// Parse the DTD external subset
dtdsub();
} else {
// Unresolved DTD external subset
skippedEnt("[dtd]");
// Release reader and stream
if (is.getCharacterStream() != null) {
try {
is.getCharacterStream().close();
} catch (IOException ioe) {
}
}
if (is.getByteStream() != null) {
try {
is.getByteStream().close();
} catch (IOException ioe) {
}
}
}
} else {
// Unresolved DTD external subset
skippedEnt("[dtd]");
}
del(psid);
}
st = -1; // end of DTD
break;
case ' ':
// skip white spaces
break;
default:
panic(FAULT);
}
break;
default:
panic(FAULT);
}
}
}
/**
* Parses the document type declaration subset.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private void dtdsub() throws Exception {
char ch;
for (short st = 0; st >= 0;) {
ch = getch();
switch (st) {
case 0: // skip white spaces before a declaration
switch (chtyp(ch)) {
case '<':
ch = getch();
switch (ch) {
case '?':
pi();
break;
case '!':
ch = getch();
bkch();
if (ch == '-') {
comm();
break;
}
// A markup or an entity declaration
bntok();
switch (bkeyword()) {
case 'n':
dtdent();
break;
case 'a':
dtdattl(); // parse attributes declaration
break;
case 'e':
dtdelm(); // parse element declaration
break;
case 'o':
dtdnot(); // parse notation declaration
break;
default:
panic(FAULT); // unsupported markup declaration
break;
}
st = 1; // read the end of declaration
break;
default:
panic(FAULT);
break;
}
break;
case '%':
// A parameter entity reference
pent(' ');
break;
case ']':
// End of DTD subset
st = -1;
break;
case ' ':
// Skip white spaces
break;
case 'Z':
// End of stream
if (getch() != ']') {
panic(FAULT);
}
st = -1;
break;
default:
panic(FAULT);
}
break;
case 1: // read the end of declaration
switch (ch) {
case '>': // there is no notation
st = 0; // skip white spaces before a declaration
break;
case ' ':
case '\n':
case '\r':
case '\t':
// Skip white spaces
break;
default:
panic(FAULT);
break;
}
break;
default:
panic(FAULT);
}
}
}
/**
* Parses an entity declaration. This method fills the general (
* <code>mEnt</code>) and parameter
* (
* <code>mPEnt</code>) entity look up table.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private void dtdent() throws Exception {
String str = null;
char[] val = null;
Input inp = null;
Pair ids = null;
char ch;
for (short st = 0; st >= 0;) {
ch = getch();
switch (st) {
case 0: // skip white spaces before entity name
switch (chtyp(ch)) {
case ' ':
// Skip white spaces
break;
case '%':
// Parameter entity or parameter entity declaration.
ch = getch();
bkch();
if (chtyp(ch) == ' ') {
// Parameter entity declaration.
wsskip();
str = name(false);
switch (chtyp(wsskip())) {
case 'A':
// Read the external identifier
ids = pubsys(' ');
if (wsskip() == '>') {
// External parsed entity
if (mPEnt.containsKey(str) == false) { // [#4.2]
inp = new Input();
inp.pubid = ids.name;
inp.sysid = ids.value;
mPEnt.put(str, inp);
}
} else {
panic(FAULT);
}
del(ids);
st = -1; // the end of declaration
break;
case '\"':
case '\'':
// Read the parameter entity value
bqstr('d');
// Create the parameter entity value
val = new char[mBuffIdx + 1];
System.arraycopy(mBuff, 1, val, 1, val.length - 1);
// Add surrounding spaces [#4.4.8]
val[0] = ' ';
// Add the entity to the entity look up table
if (mPEnt.containsKey(str) == false) { // [#4.2]
inp = new Input(val);
inp.pubid = mInp.pubid;
inp.sysid = mInp.sysid;
inp.xmlenc = mInp.xmlenc;
inp.xmlver = mInp.xmlver;
mPEnt.put(str, inp);
}
st = -1; // the end of declaration
break;
default:
panic(FAULT);
break;
}
} else {
// Parameter entity reference.
pent(' ');
}
break;
default:
bkch();
str = name(false);
st = 1; // read entity declaration value
break;
}
break;
case 1: // read entity declaration value
switch (chtyp(ch)) {
case '\"': // internal entity
case '\'':
bkch();
bqstr('d'); // read a string into the buffer
if (mEnt.get(str) == null) {
// Create general entity value
val = new char[mBuffIdx];
System.arraycopy(mBuff, 1, val, 0, val.length);
// Add the entity to the entity look up table
if (mEnt.containsKey(str) == false) { // [#4.2]
inp = new Input(val);
inp.pubid = mInp.pubid;
inp.sysid = mInp.sysid;
inp.xmlenc = mInp.xmlenc;
inp.xmlver = mInp.xmlver;
mEnt.put(str, inp);
}
}
st = -1; // the end of declaration
break;
case 'A': // external entity
bkch();
ids = pubsys(' ');
switch (wsskip()) {
case '>': // external parsed entity
if (mEnt.containsKey(str) == false) { // [#4.2]
inp = new Input();
inp.pubid = ids.name;
inp.sysid = ids.value;
mEnt.put(str, inp);
}
break;
case 'N': // external general unparsed entity
if ("NDATA".equals(name(false)) == true) {
wsskip();
unparsedEntDecl(str, ids.name, ids.value, name(false));
break;
}
default:
panic(FAULT);
break;
}
del(ids);
st = -1; // the end of declaration
break;
case ' ':
// Skip white spaces
break;
default:
panic(FAULT);
break;
}
break;
default:
panic(FAULT);
}
}
}
/**
* Parses an element declaration.
*
* This method parses the declaration up to the closing angle bracket.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private void dtdelm() throws Exception {
// This is stub implementation which skips an element
// declaration.
wsskip();
name(mIsNSAware);
char ch;
while (true) {
ch = getch();
switch (ch) {
case '>':
bkch();
return;
case EOS:
panic(FAULT);
default:
break;
}
}
}
/**
* Parses an attribute list declaration.
*
* This method parses the declaration up to the closing angle bracket.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private void dtdattl() throws Exception {
char elmqn[] = null;
Pair elm = null;
char ch;
for (short st = 0; st >= 0;) {
ch = getch();
switch (st) {
case 0: // read the element name
switch (chtyp(ch)) {
case 'a':
case 'A':
case '_':
case 'X':
case ':':
bkch();
// Get the element from the list or add a new one.
elmqn = qname(mIsNSAware);
elm = find(mAttL, elmqn);
if (elm == null) {
elm = pair(mAttL);
elm.chars = elmqn;
mAttL = elm;
}
st = 1; // read an attribute declaration
break;
case ' ':
break;
case '%':
pent(' ');
break;
default:
panic(FAULT);
break;
}
break;
case 1: // read an attribute declaration
switch (chtyp(ch)) {
case 'a':
case 'A':
case '_':
case 'X':
case ':':
bkch();
dtdatt(elm);
if (wsskip() == '>') {
return;
}
break;
case ' ':
break;
case '%':
pent(' ');
break;
default:
panic(FAULT);
break;
}
break;
default:
panic(FAULT);
break;
}
}
}
/**
* Parses an attribute declaration.
*
* The attribute uses the following fields of Pair object: chars - characters
* of qualified name id - the type identifier of the attribute list - a pair
* which holds the default value (chars field)
*
* @param elm An object which represents all defined attributes on an
* element.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private void dtdatt(Pair elm) throws Exception {
char attqn[] = null;
Pair att = null;
char ch;
for (short st = 0; st >= 0;) {
ch = getch();
switch (st) {
case 0: // the attribute name
switch (chtyp(ch)) {
case 'a':
case 'A':
case '_':
case 'X':
case ':':
bkch();
// Get the attribut from the list or add a new one.
attqn = qname(mIsNSAware);
att = find(elm.list, attqn);
if (att == null) {
// New attribute declaration
att = pair(elm.list);
att.chars = attqn;
elm.list = att;
} else {
// Do not override the attribute declaration [#3.3]
att = pair(null);
att.chars = attqn;
att.id = 'c';
}
wsskip();
st = 1;
break;
case '%':
pent(' ');
break;
case ' ':
break;
default:
panic(FAULT);
break;
}
break;
case 1: // the attribute type
switch (chtyp(ch)) {
case '(':
att.id = 'u'; // enumeration type
st = 2; // read the first element of the list
break;
case '%':
pent(' ');
break;
case ' ':
break;
default:
bkch();
bntok(); // read type id
att.id = bkeyword();
switch (att.id) {
case 'o': // NOTATION
if (wsskip() != '(') {
panic(FAULT);
}
ch = getch();
st = 2; // read the first element of the list
break;
case 'i': // ID
case 'r': // IDREF
case 'R': // IDREFS
case 'n': // ENTITY
case 'N': // ENTITIES
case 't': // NMTOKEN
case 'T': // NMTOKENS
case 'c': // CDATA
wsskip();
st = 4; // read default declaration
break;
default:
panic(FAULT);
break;
}
break;
}
break;
case 2: // read the first element of the list
switch (chtyp(ch)) {
case 'a':
case 'A':
case 'd':
case '.':
case ':':
case '-':
case '_':
case 'X':
bkch();
switch (att.id) {
case 'u': // enumeration type
bntok();
break;
case 'o': // NOTATION
mBuffIdx = -1;
bname(false);
break;
default:
panic(FAULT);
break;
}
wsskip();
st = 3; // read next element of the list
break;
case '%':
pent(' ');
break;
case ' ':
break;
default:
panic(FAULT);
break;
}
break;
case 3: // read next element of the list
switch (ch) {
case ')':
wsskip();
st = 4; // read default declaration
break;
case '|':
wsskip();
switch (att.id) {
case 'u': // enumeration type
bntok();
break;
case 'o': // NOTATION
mBuffIdx = -1;
bname(false);
break;
default:
panic(FAULT);
break;
}
wsskip();
break;
case '%':
pent(' ');
break;
default:
panic(FAULT);
break;
}
break;
case 4: // read default declaration
switch (ch) {
case '#':
bntok();
switch (bkeyword()) {
case 'F': // FIXED
switch (wsskip()) {
case '\"':
case '\'':
st = 5; // read the default value
break;
case EOS:
panic(FAULT);
default:
st = -1;
break;
}
break;
case 'Q': // REQUIRED
case 'I': // IMPLIED
st = -1;
break;
default:
panic(FAULT);
break;
}
break;
case '\"':
case '\'':
bkch();
st = 5; // read the default value
break;
case ' ':
case '\n':
case '\r':
case '\t':
break;
case '%':
pent(' ');
break;
default:
bkch();
st = -1;
break;
}
break;
case 5: // read the default value
switch (ch) {
case '\"':
case '\'':
bkch();
bqstr('d'); // the value in the mBuff now
att.list = pair(null);
// Create a string like "attqname='value' "
att.list.chars = new char[att.chars.length + mBuffIdx + 3];
System.arraycopy(
att.chars, 1, att.list.chars, 0, att.chars.length - 1);
att.list.chars[att.chars.length - 1] = '=';
att.list.chars[att.chars.length] = ch;
System.arraycopy(
mBuff, 1, att.list.chars, att.chars.length + 1, mBuffIdx);
att.list.chars[att.chars.length + mBuffIdx + 1] = ch;
att.list.chars[att.chars.length + mBuffIdx + 2] = ' ';
st = -1;
break;
default:
panic(FAULT);
break;
}
break;
default:
panic(FAULT);
break;
}
}
}
/**
* Parses a notation declaration.
*
* This method parses the declaration up to the closing angle bracket.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private void dtdnot() throws Exception {
wsskip();
String name = name(false);
wsskip();
Pair ids = pubsys('N');
notDecl(name, ids.name, ids.value);
del(ids);
}
/**
* Parses an attribute.
*
* This recursive method is responsible for prefix addition
* (
* <code>mPref</code>) on the way down. The element's start tag end triggers
* the return process. The method then on it's way back resolves prefixes
* and accumulates attributes.
*
* <p><code>att.num</code> carries attribute flags where: 0x1 - attribute is
* declared in DTD (attribute decalration had been read); 0x2 - attribute's
* default value is used.</p>
*
* @param att An object which reprecents current attribute.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private void attr(Pair att) throws Exception {
switch (wsskip()) {
case '/':
case '>':
if ((att.num & 0x2) == 0) { // all attributes have been read
att.num |= 0x2; // set default attribute flag
Input inp = mInp;
// Go through all attributes defined on current element.
for (Pair def = mElm.list; def != null; def = def.next) {
if (def.list == null) // no default value
{
continue;
}
// Go through all attributes defined on current
// element and add defaults.
Pair act = find(att.next, def.chars);
if (act == null) {
push(new Input(def.list.chars));
}
}
if (mInp != inp) { // defaults have been added
attr(att);
return;
}
}
// Ensure the attribute string array capacity
mAttrs.setLength(mAttrIdx);
mItems = mAttrs.mItems;
return;
case EOS:
panic(FAULT);
default:
// Read the attribute name and value
att.chars = qname(mIsNSAware);
att.name = att.local();
String type = atype(att); // sets attribute's type on att.id
wsskip();
if (getch() != '=') {
panic(FAULT);
}
bqstr((char) att.id); // read the value with normalization.
String val = new String(mBuff, 1, mBuffIdx);
Pair next = pair(att);
next.num = (att.num & ~0x1); // inherit attribute flags
// Put a namespace declaration on top of the prefix stack
if ((mIsNSAware == false) || (isdecl(att, val) == false)) {
// An ordinary attribute
mAttrIdx++;
attr(next); // recursive call to parse the next attribute
mAttrIdx--;
// Add the attribute to the attributes string array
char idx = (char) (mAttrIdx << 3);
mItems[idx + 1] = att.qname(); // attr qname
mItems[idx + 2] = (mIsNSAware) ? att.name : ""; // attr local name
mItems[idx + 3] = val; // attr value
mItems[idx + 4] = type; // attr type
switch (att.num & 0x3) {
case 0x0:
mItems[idx + 5] = null;
break;
case 0x1: // declared attribute
mItems[idx + 5] = "d";
break;
default: // 0x2, 0x3 - default attribute always declared
mItems[idx + 5] = "D";
break;
}
// Resolve the prefix if any and report the attribute
// NOTE: The attribute does not accept the default namespace.
mItems[idx + 0] = (att.chars[0] != 0) ? rslv(att.chars) : "";
} else {
// A namespace declaration. mPref.name contains prefix and
// mPref.value contains namespace URI set by isdecl method.
// Report a start of the new mapping
newPrefix();
// Recursive call to parse the next attribute
attr(next);
// NOTE: The namespace declaration is not reported.
}
del(next);
break;
}
}
/**
* Retrieves attribute type.
*
* This method sets the type of normalization in the attribute
* <code>id</code> field and returns the name of attribute type.
*
* @param att An object which represents current attribute.
* @return The name of the attribute type.
* @exception Exception is parser specific exception form panic method.
*/
private String atype(Pair att)
throws Exception {
Pair attr;
// CDATA-type normalization by default [#3.3.3]
att.id = 'c';
if (mElm.list == null || (attr = find(mElm.list, att.chars)) == null) {
return "CDATA";
}
att.num |= 0x1; // attribute is declared
// Non-CDATA normalization except when the attribute type is CDATA.
att.id = 'i';
switch (attr.id) {
case 'i':
return "ID";
case 'r':
return "IDREF";
case 'R':
return "IDREFS";
case 'n':
return "ENTITY";
case 'N':
return "ENTITIES";
case 't':
return "NMTOKEN";
case 'T':
return "NMTOKENS";
case 'u':
return "NMTOKEN";
case 'o':
return "NOTATION";
case 'c':
att.id = 'c';
return "CDATA";
default:
panic(FAULT);
}
return null;
}
/**
* Parses a comment.
*
* The &apos;&lt;!&apos; part is read in dispatcher so the method starts
* with first &apos;-&apos; after &apos;&lt;!&apos;.
*
* @exception Exception is parser specific exception form panic method.
*/
@SuppressWarnings("fallthrough")
private void comm() throws Exception {
if (mPh == PH_DOC_START) {
mPh = PH_MISC_DTD; // misc before DTD
} // '<!' has been already read by dispetcher.
char ch;
mBuffIdx = -1;
for (short st = 0; st >= 0;) {
ch = (mChIdx < mChLen) ? mChars[mChIdx++] : getch();
if (ch == EOS) {
panic(FAULT);
}
switch (st) {
case 0: // first '-' of the comment open
if (ch == '-') {
st = 1;
} else {
panic(FAULT);
}
break;
case 1: // secind '-' of the comment open
if (ch == '-') {
st = 2;
} else {
panic(FAULT);
}
break;
case 2: // skip the comment body
switch (ch) {
case '-':
st = 3;
break;
default:
bappend(ch);
break;
}
break;
case 3: // second '-' of the comment close
switch (ch) {
case '-':
st = 4;
break;
default:
bappend('-');
bappend(ch);
st = 2;
break;
}
break;
case 4: // '>' of the comment close
if (ch == '>') {
comm(mBuff, mBuffIdx + 1);
st = -1;
break;
}
// else - panic [#2.5 compatibility note]
default:
panic(FAULT);
}
}
}
/**
* Parses a processing instruction.
*
* The &apos;&lt;?&apos; is read in dispatcher so the method starts with
* first character of PI target name after &apos;&lt;?&apos;.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private void pi() throws Exception {
// '<?' has been already read by dispetcher.
char ch;
String str = null;
mBuffIdx = -1;
for (short st = 0; st >= 0;) {
ch = getch();
if (ch == EOS) {
panic(FAULT);
}
switch (st) {
case 0: // read the PI target name
switch (chtyp(ch)) {
case 'a':
case 'A':
case '_':
case ':':
case 'X':
bkch();
str = name(false);
// PI target name may not be empty string [#2.6]
// PI target name 'XML' is reserved [#2.6]
if ((str.length() == 0)
|| (mXml.name.equals(str.toLowerCase()) == true)) {
panic(FAULT);
}
// This is processing instruction
if (mPh == PH_DOC_START) // the begining of the document
{
mPh = PH_MISC_DTD; // misc before DTD
}
wsskip(); // skip spaces after the PI target name
st = 1; // accumulate the PI body
mBuffIdx = -1;
break;
default:
panic(FAULT);
}
break;
case 1: // accumulate the PI body
switch (ch) {
case '?':
st = 2; // end of the PI body
break;
default:
bappend(ch);
break;
}
break;
case 2: // end of the PI body
switch (ch) {
case '>':
// PI has been read.
pi(str, new String(mBuff, 0, mBuffIdx + 1));
st = -1;
break;
case '?':
bappend('?');
break;
default:
bappend('?');
bappend(ch);
st = 1; // accumulate the PI body
break;
}
break;
default:
panic(FAULT);
}
}
}
/**
* Parses a character data.
*
* The &apos;&lt;!&apos; part is read in dispatcher so the method starts
* with first &apos;[&apos; after &apos;&lt;!&apos;.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private void cdat()
throws Exception {
// '<!' has been already read by dispetcher.
char ch;
mBuffIdx = -1;
for (short st = 0; st >= 0;) {
ch = getch();
switch (st) {
case 0: // the first '[' of the CDATA open
if (ch == '[') {
st = 1;
} else {
panic(FAULT);
}
break;
case 1: // read "CDATA"
if (chtyp(ch) == 'A') {
bappend(ch);
} else {
if ("CDATA".equals(
new String(mBuff, 0, mBuffIdx + 1)) != true) {
panic(FAULT);
}
bkch();
st = 2;
}
break;
case 2: // the second '[' of the CDATA open
if (ch != '[') {
panic(FAULT);
}
mBuffIdx = -1;
st = 3;
break;
case 3: // read data before the first ']'
if (ch != ']') {
bappend(ch);
} else {
st = 4;
}
break;
case 4: // read the second ']' or continue to read the data
if (ch != ']') {
bappend(']');
bappend(ch);
st = 3;
} else {
st = 5;
}
break;
case 5: // read '>' or continue to read the data
switch (ch) {
case ']':
bappend(']');
break;
case '>':
bflash();
st = -1;
break;
default:
bappend(']');
bappend(']');
bappend(ch);
st = 3;
break;
}
break;
default:
panic(FAULT);
}
}
}
/**
* Reads a xml name.
*
* The xml name must conform "Namespaces in XML" specification. Therefore
* the ':' character is not allowed in the name. This method should be used
* for PI and entity names which may not have a namespace according to the
* specification mentioned above.
*
* @param ns The true value turns namespace conformance on.
* @return The name has been read.
* @exception Exception When incorrect character appear in the name.
* @exception IOException
*/
protected String name(boolean ns)
throws Exception {
mBuffIdx = -1;
bname(ns);
return new String(mBuff, 1, mBuffIdx);
}
/**
* Reads a qualified xml name.
*
* The characters of a qualified name is an array of characters. The first
* (chars[0]) character is the index of the colon character which separates
* the prefix from the local name. If the index is zero, the name does not
* contain separator or the parser works in the namespace unaware mode. The
* length of qualified name is the length of the array minus one.
*
* @param ns The true value turns namespace conformance on.
* @return The characters of a qualified name.
* @exception Exception When incorrect character appear in the name.
* @exception IOException
*/
protected char[] qname(boolean ns)
throws Exception {
mBuffIdx = -1;
bname(ns);
char chars[] = new char[mBuffIdx + 1];
System.arraycopy(mBuff, 0, chars, 0, mBuffIdx + 1);
return chars;
}
/**
* Reads the public or/and system identifiers.
*
* @param inp The input object.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private void pubsys(Input inp)
throws Exception {
Pair pair = pubsys(' ');
inp.pubid = pair.name;
inp.sysid = pair.value;
del(pair);
}
/**
* Reads the public or/and system identifiers.
*
* @param flag The 'N' allows public id be without system id.
* @return The public or/and system identifiers pair.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private Pair pubsys(char flag) throws Exception {
Pair ids = pair(null);
String str = name(false);
if ("PUBLIC".equals(str) == true) {
bqstr('i'); // non-CDATA normalization [#4.2.2]
ids.name = new String(mBuff, 1, mBuffIdx);
switch (wsskip()) {
case '\"':
case '\'':
bqstr(' ');
ids.value = new String(mBuff, 1, mBuffIdx);
break;
case EOS:
panic(FAULT);
default:
if (flag != 'N') // [#4.7]
{
panic(FAULT);
}
ids.value = null;
break;
}
return ids;
} else if ("SYSTEM".equals(str) == true) {
ids.name = null;
bqstr(' ');
ids.value = new String(mBuff, 1, mBuffIdx);
return ids;
}
panic(FAULT);
return null;
}
/**
* Reads an attribute value.
*
* The grammar which this method can read is:<br />
* <code>eqstr := S &quot;=&quot; qstr</code><br />
* <code>qstr := S (&quot;'&quot; string &quot;'&quot;) |
* ('&quot;' string '&quot;')</code><br /> This method resolves entities
* inside a string unless the parser parses DTD.
*
* @param flag The '=' character forces the method to accept the '='
* character before quoted string and read the following string as not an
* attribute ('-'), 'c' - CDATA, 'i' - non CDATA, ' ' - no normalization;
* '-' - not an attribute value; 'd' - in DTD context.
* @return The content of the quoted strign as a string.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
protected String eqstr(char flag) throws Exception {
if (flag == '=') {
wsskip();
if (getch() != '=') {
panic(FAULT);
}
}
bqstr((flag == '=') ? '-' : flag);
return new String(mBuff, 1, mBuffIdx);
}
/**
* Resoves an entity.
*
* This method resolves built-in and character entity references. It is also
* reports external entities to the application.
*
* @param flag The 'x' character forces the method to report a skipped
* entity; 'i' character - indicates non-CDATA normalization.
* @return Name of unresolved entity or <code>null</code> if entity had been
* resolved successfully.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private String ent(char flag) throws Exception {
char ch;
int idx = mBuffIdx + 1;
Input inp = null;
String str = null;
mESt = 0x100; // reset the built-in entity recognizer
bappend('&');
for (short st = 0; st >= 0;) {
ch = (mChIdx < mChLen) ? mChars[mChIdx++] : getch();
switch (st) {
case 0: // the first character of the entity name
case 1: // read built-in entity name
switch (chtyp(ch)) {
case 'd':
case '.':
case '-':
if (st != 1) {
panic(FAULT);
}
case 'a':
case 'A':
case '_':
case 'X':
bappend(ch);
eappend(ch);
st = 1;
break;
case ':':
if (mIsNSAware != false) {
panic(FAULT);
}
bappend(ch);
eappend(ch);
st = 1;
break;
case ';':
if (mESt < 0x100) {
// The entity is a built-in entity
mBuffIdx = idx - 1;
bappend(mESt);
st = -1;
break;
} else if (mPh == PH_DTD) {
// In DTD entity declaration has to resolve character
// entities and include "as is" others. [#4.4.7]
bappend(';');
st = -1;
break;
}
// Convert an entity name to a string
str = new String(mBuff, idx + 1, mBuffIdx - idx);
inp = mEnt.get(str);
// Restore the buffer offset
mBuffIdx = idx - 1;
if (inp != null) {
if (inp.chars == null) {
// External entity
InputSource is = resolveEnt(str, inp.pubid, inp.sysid);
if (is != null) {
push(new Input(BUFFSIZE_READER));
setinp(is);
mInp.pubid = inp.pubid;
mInp.sysid = inp.sysid;
str = null; // the entity is resolved
} else {
// Unresolved external entity
if (flag != 'x') {
panic(FAULT); // unknown entity within marckup
} // str is name of unresolved entity
}
} else {
// Internal entity
push(inp);
str = null; // the entity is resolved
}
} else {
// Unknown or general unparsed entity
if (flag != 'x') {
panic(FAULT); // unknown entity within marckup
} // str is name of unresolved entity
}
st = -1;
break;
case '#':
if (st != 0) {
panic(FAULT);
}
st = 2;
break;
default:
panic(FAULT);
}
break;
case 2: // read character entity
switch (chtyp(ch)) {
case 'd':
bappend(ch);
break;
case ';':
// Convert the character entity to a character
try {
int i = Integer.parseInt(
new String(mBuff, idx + 1, mBuffIdx - idx), 10);
if (i >= 0xffff) {
panic(FAULT);
}
ch = (char) i;
} catch (NumberFormatException nfe) {
panic(FAULT);
}
// Restore the buffer offset
mBuffIdx = idx - 1;
if (ch == ' ' || mInp.next != null) {
bappend(ch, flag);
} else {
bappend(ch);
}
st = -1;
break;
case 'a':
// If the entity buffer is empty and ch == 'x'
if ((mBuffIdx == idx) && (ch == 'x')) {
st = 3;
break;
}
default:
panic(FAULT);
}
break;
case 3: // read hex character entity
switch (chtyp(ch)) {
case 'A':
case 'a':
case 'd':
bappend(ch);
break;
case ';':
// Convert the character entity to a character
try {
int i = Integer.parseInt(
new String(mBuff, idx + 1, mBuffIdx - idx), 16);
if (i >= 0xffff) {
panic(FAULT);
}
ch = (char) i;
} catch (NumberFormatException nfe) {
panic(FAULT);
}
// Restore the buffer offset
mBuffIdx = idx - 1;
if (ch == ' ' || mInp.next != null) {
bappend(ch, flag);
} else {
bappend(ch);
}
st = -1;
break;
default:
panic(FAULT);
}
break;
default:
panic(FAULT);
}
}
return str;
}
/**
* Resoves a parameter entity.
*
* This method resolves a parameter entity references. It is also reports
* external entities to the application.
*
* @param flag The '-' instruct the method to do not set up surrounding
* spaces [#4.4.8].
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private void pent(char flag) throws Exception {
char ch;
int idx = mBuffIdx + 1;
Input inp = null;
String str = null;
bappend('%');
if (mPh != PH_DTD) // the DTD internal subset
{
return; // Not Recognized [#4.4.1]
} // Read entity name
bname(false);
str = new String(mBuff, idx + 2, mBuffIdx - idx - 1);
if (getch() != ';') {
panic(FAULT);
}
inp = mPEnt.get(str);
// Restore the buffer offset
mBuffIdx = idx - 1;
if (inp != null) {
if (inp.chars == null) {
// External parameter entity
InputSource is = resolveEnt(str, inp.pubid, inp.sysid);
if (is != null) {
if (flag != '-') {
bappend(' '); // tail space
}
push(new Input(BUFFSIZE_READER));
// BUG: there is no leading space! [#4.4.8]
setinp(is);
mInp.pubid = inp.pubid;
mInp.sysid = inp.sysid;
} else {
// Unresolved external parameter entity
skippedEnt("%" + str);
}
} else {
// Internal parameter entity
if (flag == '-') {
// No surrounding spaces
inp.chIdx = 1;
} else {
// Insert surrounding spaces
bappend(' '); // tail space
inp.chIdx = 0;
}
push(inp);
}
} else {
// Unknown parameter entity
skippedEnt("%" + str);
}
}
/**
* Recognizes and handles a namespace declaration.
*
* This method identifies a type of namespace declaration if any and puts
* new mapping on top of prefix stack.
*
* @param name The attribute qualified name (<code>name.value</code> is a
* <code>String</code> object which represents the attribute prefix).
* @param value The attribute value.
* @return <code>true</code> if a namespace declaration is recognized.
*/
private boolean isdecl(Pair name, String value) {
if (name.chars[0] == 0) {
if ("xmlns".equals(name.name) == true) {
// New default namespace declaration
mPref = pair(mPref);
mPref.list = mElm; // prefix owner element
mPref.value = value;
mPref.name = "";
mPref.chars = NONS;
mElm.num++; // namespace counter
return true;
}
} else {
if (name.eqpref(XMLNS) == true) {
// New prefix declaration
int len = name.name.length();
mPref = pair(mPref);
mPref.list = mElm; // prefix owner element
mPref.value = value;
mPref.name = name.name;
mPref.chars = new char[len + 1];
mPref.chars[0] = (char) (len + 1);
name.name.getChars(0, len, mPref.chars, 1);
mElm.num++; // namespace counter
return true;
}
}
return false;
}
/**
* Resolves a prefix.
*
* @return The namespace assigned to the prefix.
* @exception Exception When mapping for specified prefix is not found.
*/
private String rslv(char[] qname)
throws Exception {
for (Pair pref = mPref; pref != null; pref = pref.next) {
if (pref.eqpref(qname) == true) {
return pref.value;
}
}
if (qname[0] == 1) { // QNames like ':local'
for (Pair pref = mPref; pref != null; pref = pref.next) {
if (pref.chars[0] == 0) {
return pref.value;
}
}
}
panic(FAULT);
return null;
}
/**
* Skips xml white space characters.
*
* This method skips white space characters (' ', '\t', '\n', '\r') and
* looks ahead not white space character.
*
* @return The first not white space look ahead character.
* @exception IOException
*/
protected char wsskip()
throws IOException {
char ch;
while (true) {
// Read next character
ch = (mChIdx < mChLen) ? mChars[mChIdx++] : getch();
if (ch < 0x80) {
if (nmttyp[ch] != 3) // [ \t\n\r]
{
break;
}
} else {
break;
}
}
mChIdx--; // bkch();
return ch;
}
/**
* Reports document type.
*
* @param name The name of the entity.
* @param pubid The public identifier of the entity or <code>null</code>.
* @param sysid The system identifier of the entity or <code>null</code>.
*/
protected abstract void docType(String name, String pubid, String sysid)
throws SAXException;
/**
* Reports a comment.
*
* @param text The comment text starting from first charcater.
* @param length The number of characters in comment.
*/
protected abstract void comm(char[] text, int length);
/**
* Reports a processing instruction.
*
* @param target The processing instruction target name.
* @param body The processing instruction body text.
*/
protected abstract void pi(String target, String body)
throws Exception;
/**
* Reports new namespace prefix. The Namespace prefix (
* <code>mPref.name</code>) being declared and the Namespace URI (
* <code>mPref.value</code>) the prefix is mapped to. An empty string is
* used for the default element namespace, which has no prefix.
*/
protected abstract void newPrefix()
throws Exception;
/**
* Reports skipped entity name.
*
* @param name The entity name.
*/
protected abstract void skippedEnt(String name)
throws Exception;
/**
* Returns an
* <code>InputSource</code> for specified entity or
* <code>null</code>.
*
* @param name The name of the entity.
* @param pubid The public identifier of the entity.
* @param sysid The system identifier of the entity.
*/
protected abstract InputSource resolveEnt(
String name, String pubid, String sysid)
throws Exception;
/**
* Reports notation declaration.
*
* @param name The notation's name.
* @param pubid The notation's public identifier, or null if none was given.
* @param sysid The notation's system identifier, or null if none was given.
*/
protected abstract void notDecl(String name, String pubid, String sysid)
throws Exception;
/**
* Reports unparsed entity name.
*
* @param name The unparsed entity's name.
* @param pubid The entity's public identifier, or null if none was given.
* @param sysid The entity's system identifier.
* @param notation The name of the associated notation.
*/
protected abstract void unparsedEntDecl(
String name, String pubid, String sysid, String notation)
throws Exception;
/**
* Notifies the handler about fatal parsing error.
*
* @param msg The problem description message.
*/
protected abstract void panic(String msg)
throws Exception;
/**
* Reads a qualified xml name.
*
* This is low level routine which leaves a qName in the buffer. The
* characters of a qualified name is an array of characters. The first
* (chars[0]) character is the index of the colon character which separates
* the prefix from the local name. If the index is zero, the name does not
* contain separator or the parser works in the namespace unaware mode. The
* length of qualified name is the length of the array minus one.
*
* @param ns The true value turns namespace conformance on.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private void bname(boolean ns)
throws Exception {
char ch;
char type;
mBuffIdx++; // allocate a char for colon offset
int bqname = mBuffIdx;
int bcolon = bqname;
int bchidx = bqname + 1;
int bstart = bchidx;
int cstart = mChIdx;
short st = (short) ((ns == true) ? 0 : 2);
while (true) {
// Read next character
if (mChIdx >= mChLen) {
bcopy(cstart, bstart);
getch();
mChIdx--; // bkch();
cstart = mChIdx;
bstart = bchidx;
}
ch = mChars[mChIdx++];
type = (char) 0; // [X]
if (ch < 0x80) {
type = (char) nmttyp[ch];
} else if (ch == EOS) {
panic(FAULT);
}
// Parse QName
switch (st) {
case 0: // read the first char of the prefix
case 2: // read the first char of the suffix
switch (type) {
case 0: // [aA_X]
bchidx++; // append char to the buffer
st++; // (st == 0)? 1: 3;
break;
case 1: // [:]
mChIdx--; // bkch();
st++; // (st == 0)? 1: 3;
break;
default:
panic(FAULT);
}
break;
case 1: // read the prefix
case 3: // read the suffix
switch (type) {
case 0: // [aA_X]
case 2: // [.-d]
bchidx++; // append char to the buffer
break;
case 1: // [:]
bchidx++; // append char to the buffer
if (ns == true) {
if (bcolon != bqname) {
panic(FAULT); // it must be only one colon
}
bcolon = bchidx - 1;
if (st == 1) {
st = 2;
}
}
break;
default:
mChIdx--; // bkch();
bcopy(cstart, bstart);
mBuff[bqname] = (char) (bcolon - bqname);
return;
}
break;
default:
panic(FAULT);
}
}
}
/**
* Reads a nmtoken.
*
* This is low level routine which leaves a nmtoken in the buffer.
*
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private void bntok() throws Exception {
char ch;
mBuffIdx = -1;
bappend((char) 0); // default offset to the colon char
while (true) {
ch = getch();
switch (chtyp(ch)) {
case 'a':
case 'A':
case 'd':
case '.':
case ':':
case '-':
case '_':
case 'X':
bappend(ch);
break;
case 'Z':
panic(FAULT);
default:
bkch();
return;
}
}
}
/**
* Recognizes a keyword.
*
* This is low level routine which recognizes one of keywords in the buffer.
* Keyword Id ID - i IDREF - r IDREFS - R ENTITY - n ENTITIES - N NMTOKEN -
* t NMTOKENS - T ELEMENT - e ATTLIST - a NOTATION - o CDATA - c REQUIRED -
* Q IMPLIED - I FIXED - F
*
* @return an id of a keyword or '?'.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private char bkeyword()
throws Exception {
String str = new String(mBuff, 1, mBuffIdx);
switch (str.length()) {
case 2: // ID
return ("ID".equals(str) == true) ? 'i' : '?';
case 5: // IDREF, CDATA, FIXED
switch (mBuff[1]) {
case 'I':
return ("IDREF".equals(str) == true) ? 'r' : '?';
case 'C':
return ("CDATA".equals(str) == true) ? 'c' : '?';
case 'F':
return ("FIXED".equals(str) == true) ? 'F' : '?';
default:
break;
}
break;
case 6: // IDREFS, ENTITY
switch (mBuff[1]) {
case 'I':
return ("IDREFS".equals(str) == true) ? 'R' : '?';
case 'E':
return ("ENTITY".equals(str) == true) ? 'n' : '?';
default:
break;
}
break;
case 7: // NMTOKEN, IMPLIED, ATTLIST, ELEMENT
switch (mBuff[1]) {
case 'I':
return ("IMPLIED".equals(str) == true) ? 'I' : '?';
case 'N':
return ("NMTOKEN".equals(str) == true) ? 't' : '?';
case 'A':
return ("ATTLIST".equals(str) == true) ? 'a' : '?';
case 'E':
return ("ELEMENT".equals(str) == true) ? 'e' : '?';
default:
break;
}
break;
case 8: // ENTITIES, NMTOKENS, NOTATION, REQUIRED
switch (mBuff[2]) {
case 'N':
return ("ENTITIES".equals(str) == true) ? 'N' : '?';
case 'M':
return ("NMTOKENS".equals(str) == true) ? 'T' : '?';
case 'O':
return ("NOTATION".equals(str) == true) ? 'o' : '?';
case 'E':
return ("REQUIRED".equals(str) == true) ? 'Q' : '?';
default:
break;
}
break;
default:
break;
}
return '?';
}
/**
* Reads a single or double quotted string in to the buffer.
*
* This method resolves entities inside a string unless the parser parses
* DTD.
*
* @param flag 'c' - CDATA, 'i' - non CDATA, ' ' - no normalization; '-' -
* not an attribute value; 'd' - in DTD context.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
@SuppressWarnings("fallthrough")
private void bqstr(char flag) throws Exception {
Input inp = mInp; // remember the original input
mBuffIdx = -1;
bappend((char) 0); // default offset to the colon char
char ch;
for (short st = 0; st >= 0;) {
ch = (mChIdx < mChLen) ? mChars[mChIdx++] : getch();
switch (st) {
case 0: // read a single or double quote
switch (ch) {
case ' ':
case '\n':
case '\r':
case '\t':
break;
case '\'':
st = 2; // read a single quoted string
break;
case '\"':
st = 3; // read a double quoted string
break;
default:
panic(FAULT);
break;
}
break;
case 2: // read a single quoted string
case 3: // read a double quoted string
switch (ch) {
case '\'':
if ((st == 2) && (mInp == inp)) {
st = -1;
} else {
bappend(ch);
}
break;
case '\"':
if ((st == 3) && (mInp == inp)) {
st = -1;
} else {
bappend(ch);
}
break;
case '&':
if (flag != 'd') {
ent(flag);
} else {
bappend(ch);
}
break;
case '%':
if (flag == 'd') {
pent('-');
} else {
bappend(ch);
}
break;
case '<':
if ((flag == '-') || (flag == 'd')) {
bappend(ch);
} else {
panic(FAULT);
}
break;
case EOS: // EOS before single/double quote
panic(FAULT);
case '\r': // EOL processing [#2.11 & #3.3.3]
if (flag != ' ' && mInp.next == null) {
if (getch() != '\n') {
bkch();
}
ch = '\n';
}
default:
bappend(ch, flag);
break;
}
break;
default:
panic(FAULT);
}
}
// There is maximum one space at the end of the string in
// i-mode (non CDATA normalization) and it has to be removed.
if ((flag == 'i') && (mBuff[mBuffIdx] == ' ')) {
mBuffIdx -= 1;
}
}
/**
* Reports characters and empties the parser's buffer. This method is called
* only if parser is going to return control to the main loop. This means
* that this method may use parser buffer to report white space without
* copeing characters to temporary buffer.
*/
protected abstract void bflash()
throws Exception;
/**
* Reports white space characters and empties the parser's buffer. This
* method is called only if parser is going to return control to the main
* loop. This means that this method may use parser buffer to report white
* space without copeing characters to temporary buffer.
*/
protected abstract void bflash_ws()
throws Exception;
/**
* Appends a character to parser's buffer with normalization.
*
* @param ch The character to append to the buffer.
* @param mode The normalization mode.
*/
private void bappend(char ch, char mode) {
// This implements attribute value normalization as
// described in the XML specification [#3.3.3].
switch (mode) {
case 'i': // non CDATA normalization
switch (ch) {
case ' ':
case '\n':
case '\r':
case '\t':
if ((mBuffIdx > 0) && (mBuff[mBuffIdx] != ' ')) {
bappend(' ');
}
return;
default:
break;
}
break;
case 'c': // CDATA normalization
switch (ch) {
case '\n':
case '\r':
case '\t':
ch = ' ';
break;
default:
break;
}
break;
default: // no normalization
break;
}
mBuffIdx++;
if (mBuffIdx < mBuff.length) {
mBuff[mBuffIdx] = ch;
} else {
mBuffIdx--;
bappend(ch);
}
}
/**
* Appends a character to parser's buffer.
*
* @param ch The character to append to the buffer.
*/
private void bappend(char ch) {
try {
mBuff[++mBuffIdx] = ch;
} catch (Exception exp) {
// Double the buffer size
char buff[] = new char[mBuff.length << 1];
System.arraycopy(mBuff, 0, buff, 0, mBuff.length);
mBuff = buff;
mBuff[mBuffIdx] = ch;
}
}
/**
* Appends (mChIdx - cidx) characters from character buffer (mChars) to
* parser's buffer (mBuff).
*
* @param cidx The character buffer (mChars) start index.
* @param bidx The parser buffer (mBuff) start index.
*/
private void bcopy(int cidx, int bidx) {
int length = mChIdx - cidx;
if ((bidx + length + 1) >= mBuff.length) {
// Expand the buffer
char buff[] = new char[mBuff.length + length];
System.arraycopy(mBuff, 0, buff, 0, mBuff.length);
mBuff = buff;
}
System.arraycopy(mChars, cidx, mBuff, bidx, length);
mBuffIdx += length;
}
/**
* Recognizes the built-in entities <i>lt</i>, <i>gt</i>, <i>amp</i>,
* <i>apos</i>, <i>quot</i>. The initial state is 0x100. Any state belowe
* 0x100 is a built-in entity replacement character.
*
* @param ch the next character of an entity name.
*/
@SuppressWarnings("fallthrough")
private void eappend(char ch) {
switch (mESt) {
case 0x100: // "l" or "g" or "a" or "q"
switch (ch) {
case 'l':
mESt = 0x101;
break;
case 'g':
mESt = 0x102;
break;
case 'a':
mESt = 0x103;
break;
case 'q':
mESt = 0x107;
break;
default:
mESt = 0x200;
break;
}
break;
case 0x101: // "lt"
mESt = (ch == 't') ? '<' : (char) 0x200;
break;
case 0x102: // "gt"
mESt = (ch == 't') ? '>' : (char) 0x200;
break;
case 0x103: // "am" or "ap"
switch (ch) {
case 'm':
mESt = 0x104;
break;
case 'p':
mESt = 0x105;
break;
default:
mESt = 0x200;
break;
}
break;
case 0x104: // "amp"
mESt = (ch == 'p') ? '&' : (char) 0x200;
break;
case 0x105: // "apo"
mESt = (ch == 'o') ? (char) 0x106 : (char) 0x200;
break;
case 0x106: // "apos"
mESt = (ch == 's') ? '\'' : (char) 0x200;
break;
case 0x107: // "qu"
mESt = (ch == 'u') ? (char) 0x108 : (char) 0x200;
break;
case 0x108: // "quo"
mESt = (ch == 'o') ? (char) 0x109 : (char) 0x200;
break;
case 0x109: // "quot"
mESt = (ch == 't') ? '\"' : (char) 0x200;
break;
case '<': // "lt"
case '>': // "gt"
case '&': // "amp"
case '\'': // "apos"
case '\"': // "quot"
mESt = 0x200;
default:
break;
}
}
/**
* Sets up a new input source on the top of the input stack. Note, the first
* byte returned by the entity's byte stream has to be the first byte in the
* entity. However, the parser does not expect the byte order mask in both
* cases when encoding is provided by the input source.
*
* @param is A new input source to set up.
* @exception IOException If any IO errors occur.
* @exception Exception is parser specific exception form panic method.
*/
protected void setinp(InputSource is)
throws Exception {
Reader reader = null;
mChIdx = 0;
mChLen = 0;
mChars = mInp.chars;
mInp.src = null;
if (mPh < PH_DOC_START) {
mIsSAlone = false; // default [#2.9]
}
mIsSAloneSet = false;
if (is.getCharacterStream() != null) {
// Ignore encoding in the xml text decl.
reader = is.getCharacterStream();
xml(reader);
} else if (is.getByteStream() != null) {
String expenc;
if (is.getEncoding() != null) {
// Ignore encoding in the xml text decl.
expenc = is.getEncoding().toUpperCase();
if (expenc.equals("UTF-16")) {
reader = bom(is.getByteStream(), 'U'); // UTF-16 [#4.3.3]
} else {
reader = enc(expenc, is.getByteStream());
}
xml(reader);
} else {
// Get encoding from BOM or the xml text decl.
reader = bom(is.getByteStream(), ' ');
if (reader == null) {
// Encoding is defined by the xml text decl.
reader = enc("UTF-8", is.getByteStream());
expenc = xml(reader);
if (expenc.startsWith("UTF-16")) {
panic(FAULT); // UTF-16 must have BOM [#4.3.3]
}
reader = enc(expenc, is.getByteStream());
} else {
// Encoding is defined by the BOM.
xml(reader);
}
}
} else {
// There is no support for public/system identifiers.
panic(FAULT);
}
mInp.src = reader;
mInp.pubid = is.getPublicId();
mInp.sysid = is.getSystemId();
}
/**
* Determines the entity encoding.
*
* This method gets encoding from Byte Order Mask [#4.3.3] if any. Note, the
* first byte returned by the entity's byte stream has to be the first byte
* in the entity. Also, there is no support for UCS-4.
*
* @param is A byte stream of the entity.
* @param hint An encoding hint, character U means UTF-16.
* @return a reader constructed from the BOM or UTF-8 by default.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private Reader bom(InputStream is, char hint)
throws Exception {
int val = is.read();
switch (val) {
case 0xef: // UTF-8
if (hint == 'U') // must be UTF-16
{
panic(FAULT);
}
if (is.read() != 0xbb) {
panic(FAULT);
}
if (is.read() != 0xbf) {
panic(FAULT);
}
return new ReaderUTF8(is);
case 0xfe: // UTF-16, big-endian
if (is.read() != 0xff) {
panic(FAULT);
}
return new ReaderUTF16(is, 'b');
case 0xff: // UTF-16, little-endian
if (is.read() != 0xfe) {
panic(FAULT);
}
return new ReaderUTF16(is, 'l');
case -1:
mChars[mChIdx++] = EOS;
return new ReaderUTF8(is);
default:
if (hint == 'U') // must be UTF-16
{
panic(FAULT);
}
// Read the rest of UTF-8 character
switch (val & 0xf0) {
case 0xc0:
case 0xd0:
mChars[mChIdx++] = (char) (((val & 0x1f) << 6) | (is.read() & 0x3f));
break;
case 0xe0:
mChars[mChIdx++] = (char) (((val & 0x0f) << 12)
| ((is.read() & 0x3f) << 6) | (is.read() & 0x3f));
break;
case 0xf0: // UCS-4 character
throw new UnsupportedEncodingException();
default:
mChars[mChIdx++] = (char) val;
break;
}
return null;
}
}
/**
* Parses the xml text declaration.
*
* This method gets encoding from the xml text declaration [#4.3.1] if any.
* The method assumes the buffer (mChars) is big enough to accomodate whole
* xml text declaration.
*
* @param reader is entity reader.
* @return The xml text declaration encoding or default UTF-8 encoding.
* @exception Exception is parser specific exception form panic method.
* @exception IOException
*/
private String xml(Reader reader)
throws Exception {
String str = null;
String enc = "UTF-8";
char ch;
int val;
short st;
// Read the xml text declaration into the buffer
if (mChIdx != 0) {
// The bom method have read ONE char into the buffer.
st = (short) ((mChars[0] == '<') ? 1 : -1);
} else {
st = 0;
}
while (st >= 0 && mChIdx < mChars.length) {
ch = ((val = reader.read()) >= 0) ? (char) val : EOS;
mChars[mChIdx++] = ch;
switch (st) {
case 0: // read '<' of xml declaration
switch (ch) {
case '<':
st = 1;
break;
case 0xfeff: // the byte order mask
ch = ((val = reader.read()) >= 0) ? (char) val : EOS;
mChars[mChIdx - 1] = ch;
st = (short) ((ch == '<') ? 1 : -1);
break;
default:
st = -1;
break;
}
break;
case 1: // read '?' of xml declaration [#4.3.1]
st = (short) ((ch == '?') ? 2 : -1);
break;
case 2: // read 'x' of xml declaration [#4.3.1]
st = (short) ((ch == 'x') ? 3 : -1);
break;
case 3: // read 'm' of xml declaration [#4.3.1]
st = (short) ((ch == 'm') ? 4 : -1);
break;
case 4: // read 'l' of xml declaration [#4.3.1]
st = (short) ((ch == 'l') ? 5 : -1);
break;
case 5: // read white space after 'xml'
switch (ch) {
case ' ':
case '\t':
case '\r':
case '\n':
st = 6;
break;
default:
st = -1;
break;
}
break;
case 6: // read content of xml declaration
switch (ch) {
case '?':
st = 7;
break;
case EOS:
st = -2;
break;
default:
break;
}
break;
case 7: // read '>' after '?' of xml declaration
switch (ch) {
case '>':
case EOS:
st = -2;
break;
default:
st = 6;
break;
}
break;
default:
panic(FAULT);
break;
}
}
mChLen = mChIdx;
mChIdx = 0;
// If there is no xml text declaration, the encoding is default.
if (st == -1) {
return enc;
}
mChIdx = 5; // the first white space after "<?xml"
// Parse the xml text declaration
for (st = 0; st >= 0;) {
ch = getch();
switch (st) {
case 0: // skip spaces after the xml declaration name
if (chtyp(ch) != ' ') {
bkch();
st = 1;
}
break;
case 1: // read xml declaration version
case 2: // read xml declaration encoding or standalone
case 3: // read xml declaration standalone
switch (chtyp(ch)) {
case 'a':
case 'A':
case '_':
bkch();
str = name(false).toLowerCase();
if ("version".equals(str) == true) {
if (st != 1) {
panic(FAULT);
}
if ("1.0".equals(eqstr('=')) != true) {
panic(FAULT);
}
mInp.xmlver = 0x0100;
st = 2;
} else if ("encoding".equals(str) == true) {
if (st != 2) {
panic(FAULT);
}
mInp.xmlenc = eqstr('=').toUpperCase();
enc = mInp.xmlenc;
st = 3;
} else if ("standalone".equals(str) == true) {
if ((st == 1) || (mPh >= PH_DOC_START)) // [#4.3.1]
{
panic(FAULT);
}
str = eqstr('=').toLowerCase();
// Check the 'standalone' value and use it [#5.1]
if (str.equals("yes") == true) {
mIsSAlone = true;
} else if (str.equals("no") == true) {
mIsSAlone = false;
} else {
panic(FAULT);
}
mIsSAloneSet = true;
st = 4;
} else {
panic(FAULT);
}
break;
case ' ':
break;
case '?':
if (st == 1) {
panic(FAULT);
}
bkch();
st = 4;
break;
default:
panic(FAULT);
}
break;
case 4: // end of xml declaration
switch (chtyp(ch)) {
case '?':
if (getch() != '>') {
panic(FAULT);
}
if (mPh <= PH_DOC_START) {
mPh = PH_MISC_DTD; // misc before DTD
}
st = -1;
break;
case ' ':
break;
default:
panic(FAULT);
}
break;
default:
panic(FAULT);
}
}
return enc;
}
/**
* Sets up the document reader.
*
* @param name an encoding name.
* @param is the document byte input stream.
* @return a reader constructed from encoding name and input stream.
* @exception UnsupportedEncodingException
*/
private Reader enc(String name, InputStream is)
throws UnsupportedEncodingException {
// DO NOT CLOSE current reader if any!
if (name.equals("UTF-8")) {
return new ReaderUTF8(is);
} else if (name.equals("UTF-16LE")) {
return new ReaderUTF16(is, 'l');
} else if (name.equals("UTF-16BE")) {
return new ReaderUTF16(is, 'b');
} else {
return new InputStreamReader(is, name);
}
}
/**
* Sets up current input on the top of the input stack.
*
* @param inp A new input to set up.
*/
protected void push(Input inp) {
mInp.chLen = mChLen;
mInp.chIdx = mChIdx;
inp.next = mInp;
mInp = inp;
mChars = inp.chars;
mChLen = inp.chLen;
mChIdx = inp.chIdx;
}
/**
* Restores previous input on the top of the input stack.
*/
protected void pop() {
if (mInp.src != null) {
try {
mInp.src.close();
} catch (IOException ioe) {
}
mInp.src = null;
}
mInp = mInp.next;
if (mInp != null) {
mChars = mInp.chars;
mChLen = mInp.chLen;
mChIdx = mInp.chIdx;
} else {
mChars = null;
mChLen = 0;
mChIdx = 0;
}
}
/**
* Maps a character to it's type.
*
* Possible character type values are:<br /> - ' ' for any kind of white
* space character;<br /> - 'a' for any lower case alphabetical character
* value;<br /> - 'A' for any upper case alphabetical character value;<br />
* - 'd' for any decimal digit character value;<br /> - 'z' for any
* character less then ' ' except '\t', '\n', '\r';<br /> - 'X' for any not
* ASCII character;<br /> - 'Z' for EOS character.<br /> An ASCII (7 bit)
* character which does not fall in any category listed above is mapped to
* it self.
*
* @param ch The character to map.
* @return The type of character.
*/
protected char chtyp(char ch) {
if (ch < 0x80) {
return (char) asctyp[ch];
}
return (ch != EOS) ? 'X' : 'Z';
}
/**
* Retrives the next character in the document.
*
* @return The next character in the document.
*/
protected char getch()
throws IOException {
if (mChIdx >= mChLen) {
if (mInp.src == null) {
pop(); // remove internal entity
return getch();
}
// Read new portion of the document characters
int Num = mInp.src.read(mChars, 0, mChars.length);
if (Num < 0) {
if (mInp != mDoc) {
pop(); // restore the previous input
return getch();
} else {
mChars[0] = EOS;
mChLen = 1;
}
} else {
mChLen = Num;
}
mChIdx = 0;
}
return mChars[mChIdx++];
}
/**
* Puts back the last read character.
*
* This method <strong>MUST NOT</strong> be called more then once after each
* call of {@link #getch getch} method.
*/
protected void bkch()
throws Exception {
if (mChIdx <= 0) {
panic(FAULT);
}
mChIdx--;
}
/**
* Sets the current character.
*
* @param ch The character to set.
*/
protected void setch(char ch) {
mChars[mChIdx] = ch;
}
/**
* Finds a pair in the pair chain by a qualified name.
*
* @param chain The first element of the chain of pairs.
* @param qname The qualified name.
* @return A pair with the specified qualified name or null.
*/
protected Pair find(Pair chain, char[] qname) {
for (Pair pair = chain; pair != null; pair = pair.next) {
if (pair.eqname(qname) == true) {
return pair;
}
}
return null;
}
/**
* Provedes an instance of a pair.
*
* @param next The reference to a next pair.
* @return An instance of a pair.
*/
protected Pair pair(Pair next) {
Pair pair;
if (mDltd != null) {
pair = mDltd;
mDltd = pair.next;
} else {
pair = new Pair();
}
pair.next = next;
return pair;
}
/**
* Deletes an instance of a pair.
*
* @param pair The pair to delete.
* @return A reference to the next pair in a chain.
*/
protected Pair del(Pair pair) {
Pair next = pair.next;
pair.name = null;
pair.value = null;
pair.chars = null;
pair.list = null;
pair.next = mDltd;
mDltd = pair;
return next;
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import java.io.IOException;
import java.io.InputStream;
import jdk.internal.org.xml.sax.ContentHandler;
import jdk.internal.org.xml.sax.DTDHandler;
import jdk.internal.org.xml.sax.EntityResolver;
import jdk.internal.org.xml.sax.ErrorHandler;
import jdk.internal.org.xml.sax.InputSource;
import jdk.internal.org.xml.sax.Locator;
import jdk.internal.org.xml.sax.SAXException;
import jdk.internal.org.xml.sax.SAXParseException;
import jdk.internal.org.xml.sax.XMLReader;
import jdk.internal.org.xml.sax.helpers.DefaultHandler;
/**
* XML non-validating push parser.
*
* This non-validating parser conforms to <a href="http://www.w3.org/TR/REC-xml"
* >Extensible Markup Language (XML) 1.0</a> and <a
* href="http://www.w3.org/TR/REC-xml-names" >"Namespaces in XML"</a>
* specifications. The API supported by the parser are <a
* href="http://java.sun.com/aboutJava/communityprocess/final/jsr030/index.html">CLDC
* 1.0</a> and <a href="http://www.jcp.org/en/jsr/detail?id=280">JSR-280</a>, a
* JavaME subset of <a href="http://java.sun.com/xml/jaxp/index.html">JAXP</a>
* and <a href="http://www.saxproject.org/">SAX2</a>.
*
* @see org.xml.sax.XMLReader
*/
final class ParserSAX
extends Parser implements XMLReader, Locator
{
public final static String FEATURE_NS =
"http://xml.org/sax/features/namespaces";
public final static String FEATURE_PREF =
"http://xml.org/sax/features/namespace-prefixes";
// SAX feature flags
private boolean mFNamespaces;
private boolean mFPrefixes;
// SAX handlers
private DefaultHandler mHand; // the default handler
private ContentHandler mHandCont; // the content handler
private DTDHandler mHandDtd; // the DTD handler
private ErrorHandler mHandErr; // the error handler
private EntityResolver mHandEnt; // the entity resolver
/**
* Constructor.
*/
public ParserSAX() {
super();
// SAX feature defaut values
mFNamespaces = true;
mFPrefixes = false;
// Default handler which will be used in case the application
// do not set one of handlers.
mHand = new DefaultHandler();
mHandCont = mHand;
mHandDtd = mHand;
mHandErr = mHand;
mHandEnt = mHand;
}
/**
* Return the current content handler.
*
* @return The current content handler, or null if none has been registered.
* @see #setContentHandler
*/
public ContentHandler getContentHandler() {
return (mHandCont != mHand) ? mHandCont : null;
}
/**
* Allow an application to register a content event handler.
*
* <p>If the application does not register a content handler, all content
* events reported by the SAX parser will be silently ignored.</p>
*
* <p>Applications may register a new or different handler in the middle of
* a parse, and the SAX parser must begin using the new handler
* immediately.</p>
*
* @param handler The content handler.
* @exception java.lang.NullPointerException If the handler argument is
* null.
* @see #getContentHandler
*/
public void setContentHandler(ContentHandler handler) {
if (handler == null) {
throw new NullPointerException();
}
mHandCont = handler;
}
/**
* Return the current DTD handler.
*
* @return The current DTD handler, or null if none has been registered.
* @see #setDTDHandler
*/
public DTDHandler getDTDHandler() {
return (mHandDtd != mHand) ? mHandDtd : null;
}
/**
* Allow an application to register a DTD event handler.
*
* <p>If the application does not register a DTD handler, all DTD events
* reported by the SAX parser will be silently ignored.</p>
*
* <p>Applications may register a new or different handler in the middle of
* a parse, and the SAX parser must begin using the new handler
* immediately.</p>
*
* @param handler The DTD handler.
* @exception java.lang.NullPointerException If the handler argument is
* null.
* @see #getDTDHandler
*/
public void setDTDHandler(DTDHandler handler) {
if (handler == null) {
throw new NullPointerException();
}
mHandDtd = handler;
}
/**
* Return the current error handler.
*
* @return The current error handler, or null if none has been registered.
* @see #setErrorHandler
*/
public ErrorHandler getErrorHandler() {
return (mHandErr != mHand) ? mHandErr : null;
}
/**
* Allow an application to register an error event handler.
*
* <p>If the application does not register an error handler, all error
* events reported by the SAX parser will be silently ignored; however,
* normal processing may not continue. It is highly recommended that all SAX
* applications implement an error handler to avoid unexpected bugs.</p>
*
* <p>Applications may register a new or different handler in the middle of
* a parse, and the SAX parser must begin using the new handler
* immediately.</p>
*
* @param handler The error handler.
* @exception java.lang.NullPointerException If the handler argument is
* null.
* @see #getErrorHandler
*/
public void setErrorHandler(ErrorHandler handler) {
if (handler == null) {
throw new NullPointerException();
}
mHandErr = handler;
}
/**
* Return the current entity resolver.
*
* @return The current entity resolver, or null if none has been registered.
* @see #setEntityResolver
*/
public EntityResolver getEntityResolver() {
return (mHandEnt != mHand) ? mHandEnt : null;
}
/**
* Allow an application to register an entity resolver.
*
* <p>If the application does not register an entity resolver, the XMLReader
* will perform its own default resolution.</p>
*
* <p>Applications may register a new or different resolver in the middle of
* a parse, and the SAX parser must begin using the new resolver
* immediately.</p>
*
* @param resolver The entity resolver.
* @exception java.lang.NullPointerException If the resolver argument is
* null.
* @see #getEntityResolver
*/
public void setEntityResolver(EntityResolver resolver) {
if (resolver == null) {
throw new NullPointerException();
}
mHandEnt = resolver;
}
/**
* Return the public identifier for the current document event.
*
* <p>The return value is the public identifier of the document entity or of
* the external parsed entity in which the markup triggering the event
* appears.</p>
*
* @return A string containing the public identifier, or null if none is
* available.
*
* @see #getSystemId
*/
public String getPublicId() {
return (mInp != null) ? mInp.pubid : null;
}
/**
* Return the system identifier for the current document event.
*
* <p>The return value is the system identifier of the document entity or of
* the external parsed entity in which the markup triggering the event
* appears.</p>
*
* <p>If the system identifier is a URL, the parser must resolve it fully
* before passing it to the application.</p>
*
* @return A string containing the system identifier, or null if none is
* available.
*
* @see #getPublicId
*/
public String getSystemId() {
return (mInp != null) ? mInp.sysid : null;
}
/**
* Return the line number where the current document event ends.
*
* @return Always returns -1 indicating the line number is not available.
*
* @see #getColumnNumber
*/
public int getLineNumber() {
return -1;
}
/**
* Return the column number where the current document event ends.
*
* @return Always returns -1 indicating the column number is not available.
*
* @see #getLineNumber
*/
public int getColumnNumber() {
return -1;
}
/**
* Parse an XML document from a system identifier (URI).
*
* <p>This method is a shortcut for the common case of reading a document
* from a system identifier. It is the exact equivalent of the
* following:</p>
*
* <pre>
* parse(new InputSource(systemId));
* </pre>
*
* <p>If the system identifier is a URL, it must be fully resolved by the
* application before it is passed to the parser.</p>
*
* @param systemId The system identifier (URI).
* @exception org.xml.sax.SAXException Any SAX exception, possibly wrapping
* another exception.
* @exception java.io.IOException An IO exception from the parser, possibly
* from a byte stream or character stream supplied by the application.
* @see #parse(org.xml.sax.InputSource)
*/
public void parse(String systemId) throws IOException, SAXException {
parse(new InputSource(systemId));
}
/**
* Parse an XML document.
*
* <p>The application can use this method to instruct the XML reader to
* begin parsing an XML document from any valid input source (a character
* stream, a byte stream, or a URI).</p>
*
* <p>Applications may not invoke this method while a parse is in progress
* (they should create a new XMLReader instead for each nested XML
* document). Once a parse is complete, an application may reuse the same
* XMLReader object, possibly with a different input source.</p>
*
* <p>During the parse, the XMLReader will provide information about the XML
* document through the registered event handlers.</p>
*
* <p>This method is synchronous: it will not return until parsing has
* ended. If a client application wants to terminate parsing early, it
* should throw an exception.</p>
*
* @param is The input source for the top-level of the XML document.
* @exception org.xml.sax.SAXException Any SAX exception, possibly wrapping
* another exception.
* @exception java.io.IOException An IO exception from the parser, possibly
* from a byte stream or character stream supplied by the application.
* @see org.xml.sax.InputSource
* @see #parse(java.lang.String)
* @see #setEntityResolver
* @see #setDTDHandler
* @see #setContentHandler
* @see #setErrorHandler
*/
public void parse(InputSource is) throws IOException, SAXException {
if (is == null) {
throw new IllegalArgumentException("");
}
// Set up the document
mInp = new Input(BUFFSIZE_READER);
mPh = PH_BEFORE_DOC; // before parsing
try {
setinp(is);
} catch (SAXException saxe) {
throw saxe;
} catch (IOException ioe) {
throw ioe;
} catch (RuntimeException rte) {
throw rte;
} catch (Exception e) {
panic(e.toString());
}
parse();
}
/**
* Parse the content of the given {@link java.io.InputStream} instance as
* XML using the specified {@link org.xml.sax.helpers.DefaultHandler}.
*
* @param src InputStream containing the content to be parsed.
* @param handler The SAX DefaultHandler to use.
* @exception IOException If any IO errors occur.
* @exception IllegalArgumentException If the given InputStream or handler
* is null.
* @exception SAXException If the underlying parser throws a SAXException
* while parsing.
* @see org.xml.sax.helpers.DefaultHandler
*/
public void parse(InputStream src, DefaultHandler handler)
throws SAXException, IOException {
if ((src == null) || (handler == null)) {
throw new IllegalArgumentException("");
}
parse(new InputSource(src), handler);
}
/**
* Parse the content given {@link org.xml.sax.InputSource} as XML using the
* specified {@link org.xml.sax.helpers.DefaultHandler}.
*
* @param is The InputSource containing the content to be parsed.
* @param handler The SAX DefaultHandler to use.
* @exception IOException If any IO errors occur.
* @exception IllegalArgumentException If the InputSource or handler is
* null.
* @exception SAXException If the underlying parser throws a SAXException
* while parsing.
* @see org.xml.sax.helpers.DefaultHandler
*/
public void parse(InputSource is, DefaultHandler handler)
throws SAXException, IOException
{
if ((is == null) || (handler == null)) {
throw new IllegalArgumentException("");
}
// Set up the handler
mHandCont = handler;
mHandDtd = handler;
mHandErr = handler;
mHandEnt = handler;
// Set up the document
mInp = new Input(BUFFSIZE_READER);
mPh = PH_BEFORE_DOC; // before parsing
try {
setinp(is);
} catch (SAXException | IOException | RuntimeException saxe) {
throw saxe;
} catch (Exception e) {
panic(e.toString());
}
parse();
}
/**
* Parse the XML document content using specified handlers and an input
* source.
*
* @exception IOException If any IO errors occur.
* @exception SAXException If the underlying parser throws a SAXException
* while parsing.
*/
@SuppressWarnings("fallthrough")
private void parse() throws SAXException, IOException {
init();
try {
mHandCont.setDocumentLocator(this);
mHandCont.startDocument();
if (mPh != PH_MISC_DTD) {
mPh = PH_MISC_DTD; // misc before DTD
}
int evt = EV_NULL;
// XML document prolog
do {
wsskip();
switch (evt = step()) {
case EV_ELM:
case EV_ELMS:
mPh = PH_DOCELM;
break;
case EV_COMM:
case EV_PI:
break;
case EV_DTD:
if (mPh >= PH_DTD_MISC) {
panic(FAULT);
}
mPh = PH_DTD_MISC; // misc after DTD
break;
default:
panic(FAULT);
}
} while (mPh < PH_DOCELM); // misc before DTD
// XML document starting with document's element
do {
switch (evt) {
case EV_ELM:
case EV_ELMS:
// Report the element
if (mIsNSAware == true) {
mHandCont.startElement(
mElm.value,
mElm.name,
"",
mAttrs);
} else {
mHandCont.startElement(
"",
"",
mElm.name,
mAttrs);
}
if (evt == EV_ELMS) {
evt = step();
break;
}
case EV_ELME:
// Report the end of element
if (mIsNSAware == true) {
mHandCont.endElement(mElm.value, mElm.name, "");
} else {
mHandCont.endElement("", "", mElm.name);
}
// Restore the top of the prefix stack
while (mPref.list == mElm) {
mHandCont.endPrefixMapping(mPref.name);
mPref = del(mPref);
}
// Remove the top element tag
mElm = del(mElm);
if (mElm == null) {
mPh = PH_DOCELM_MISC;
} else {
evt = step();
}
break;
case EV_TEXT:
case EV_WSPC:
case EV_CDAT:
case EV_COMM:
case EV_PI:
case EV_ENT:
evt = step();
break;
default:
panic(FAULT);
}
} while (mPh == PH_DOCELM);
// Misc after document's element
do {
if (wsskip() == EOS) {
break;
}
switch (step()) {
case EV_COMM:
case EV_PI:
break;
default:
panic(FAULT);
}
} while (mPh == PH_DOCELM_MISC);
mPh = PH_AFTER_DOC; // parsing is completed
} catch (SAXException saxe) {
throw saxe;
} catch (IOException ioe) {
throw ioe;
} catch (RuntimeException rte) {
throw rte;
} catch (Exception e) {
panic(e.toString());
} finally {
mHandCont.endDocument();
cleanup();
}
}
/**
* Reports document type.
*
* @param name The name of the entity.
* @param pubid The public identifier of the entity or <code>null</code>.
* @param sysid The system identifier of the entity or <code>null</code>.
*/
protected void docType(String name, String pubid, String sysid) throws SAXException {
mHandDtd.notationDecl(name, pubid, sysid);
}
/**
* Reports a comment.
*
* @param text The comment text starting from first charcater.
* @param length The number of characters in comment.
*/
protected void comm(char[] text, int length) {
}
/**
* Reports a processing instruction.
*
* @param target The processing instruction target name.
* @param body The processing instruction body text.
*/
protected void pi(String target, String body) throws SAXException {
mHandCont.processingInstruction(target, body);
}
/**
* Reports new namespace prefix. The Namespace prefix (
* <code>mPref.name</code>) being declared and the Namespace URI (
* <code>mPref.value</code>) the prefix is mapped to. An empty string is
* used for the default element namespace, which has no prefix.
*/
protected void newPrefix() throws SAXException {
mHandCont.startPrefixMapping(mPref.name, mPref.value);
}
/**
* Reports skipped entity name.
*
* @param name The entity name.
*/
protected void skippedEnt(String name) throws SAXException {
mHandCont.skippedEntity(name);
}
/**
* Returns an
* <code>InputSource</code> for specified entity or
* <code>null</code>.
*
* @param name The name of the entity.
* @param pubid The public identifier of the entity.
* @param sysid The system identifier of the entity.
*/
protected InputSource resolveEnt(String name, String pubid, String sysid)
throws SAXException, IOException
{
return mHandEnt.resolveEntity(pubid, sysid);
}
/**
* Reports notation declaration.
*
* @param name The notation's name.
* @param pubid The notation's public identifier, or null if none was given.
* @param sysid The notation's system identifier, or null if none was given.
*/
protected void notDecl(String name, String pubid, String sysid)
throws SAXException
{
mHandDtd.notationDecl(name, pubid, sysid);
}
/**
* Reports unparsed entity name.
*
* @param name The unparsed entity's name.
* @param pubid The entity's public identifier, or null if none was given.
* @param sysid The entity's system identifier.
* @param notation The name of the associated notation.
*/
protected void unparsedEntDecl(String name, String pubid, String sysid, String notation)
throws SAXException
{
mHandDtd.unparsedEntityDecl(name, pubid, sysid, notation);
}
/**
* Notifies the handler about fatal parsing error.
*
* @param msg The problem description message.
*/
protected void panic(String msg) throws SAXException {
SAXParseException spe = new SAXParseException(msg, this);
mHandErr.fatalError(spe);
throw spe; // [#1.2] fatal error definition
}
/**
* Reports characters and empties the parser's buffer. This method is called
* only if parser is going to return control to the main loop. This means
* that this method may use parser buffer to report white space without
* copeing characters to temporary buffer.
*/
protected void bflash() throws SAXException {
if (mBuffIdx >= 0) {
// Textual data has been read
mHandCont.characters(mBuff, 0, (mBuffIdx + 1));
mBuffIdx = -1;
}
}
/**
* Reports white space characters and empties the parser's buffer. This
* method is called only if parser is going to return control to the main
* loop. This means that this method may use parser buffer to report white
* space without copeing characters to temporary buffer.
*/
protected void bflash_ws() throws SAXException {
if (mBuffIdx >= 0) {
// BUG: With additional info from DTD and xml:space attr [#2.10]
// the following call can be supported:
// mHandCont.ignorableWhitespace(mBuff, 0, (mBuffIdx + 1));
// Textual data has been read
mHandCont.characters(mBuff, 0, (mBuffIdx + 1));
mBuffIdx = -1;
}
}
public boolean getFeature(String name) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void setFeature(String name, boolean value) {
throw new UnsupportedOperationException("Not supported yet.");
}
public Object getProperty(String name) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void setProperty(String name, Object value) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import java.io.Reader;
import java.io.InputStream;
import java.io.IOException;
/**
* UTF-16 encoded stream reader.
*/
public class ReaderUTF16 extends Reader {
private InputStream is;
private char bo;
/**
* Constructor.
*
* Byte order argument can be: 'l' for little-endian or 'b' for big-endian.
*
* @param is A byte input stream.
* @param bo A byte order in the input stream.
*/
public ReaderUTF16(InputStream is, char bo) {
switch (bo) {
case 'l':
break;
case 'b':
break;
default:
throw new IllegalArgumentException("");
}
this.bo = bo;
this.is = is;
}
/**
* Reads characters into a portion of an array.
*
* @param cbuf Destination buffer.
* @param off Offset at which to start storing characters.
* @param len Maximum number of characters to read.
* @exception IOException If any IO errors occur.
*/
public int read(char[] cbuf, int off, int len) throws IOException {
int num = 0;
int val;
if (bo == 'b') {
while (num < len) {
if ((val = is.read()) < 0) {
return (num != 0) ? num : -1;
}
cbuf[off++] = (char) ((val << 8) | (is.read() & 0xff));
num++;
}
} else {
while (num < len) {
if ((val = is.read()) < 0) {
return (num != 0) ? num : -1;
}
cbuf[off++] = (char) ((is.read() << 8) | (val & 0xff));
num++;
}
}
return num;
}
/**
* Reads a single character.
*
* @return The character read, as an integer in the range 0 to 65535
* (0x0000-0xffff), or -1 if the end of the stream has been reached.
* @exception IOException If any IO errors occur.
*/
public int read() throws IOException {
int val;
if ((val = is.read()) < 0) {
return -1;
}
if (bo == 'b') {
val = (char) ((val << 8) | (is.read() & 0xff));
} else {
val = (char) ((is.read() << 8) | (val & 0xff));
}
return val;
}
/**
* Closes the stream.
*
* @exception IOException If any IO errors occur.
*/
public void close() throws IOException {
is.close();
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import java.io.Reader;
import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* UTF-8 transformed UCS-2 character stream reader.
*
* This reader converts UTF-8 transformed UCS-2 characters to Java characters.
* The UCS-2 subset of UTF-8 transformation is described in RFC-2279 #2
* "UTF-8 definition":
* 0000 0000-0000 007F 0xxxxxxx
* 0000 0080-0000 07FF 110xxxxx 10xxxxxx
* 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
*
* This reader will return incorrect last character on broken UTF-8 stream.
*/
public class ReaderUTF8 extends Reader {
private InputStream is;
/**
* Constructor.
*
* @param is A byte input stream.
*/
public ReaderUTF8(InputStream is) {
this.is = is;
}
/**
* Reads characters into a portion of an array.
*
* @param cbuf Destination buffer.
* @param off Offset at which to start storing characters.
* @param len Maximum number of characters to read.
* @exception IOException If any IO errors occur.
* @exception UnsupportedEncodingException If UCS-4 character occur in the stream.
*/
public int read(char[] cbuf, int off, int len) throws IOException {
int num = 0;
int val;
while (num < len) {
if ((val = is.read()) < 0) {
return (num != 0) ? num : -1;
}
switch (val & 0xf0) {
case 0xc0:
case 0xd0:
cbuf[off++] = (char) (((val & 0x1f) << 6) | (is.read() & 0x3f));
break;
case 0xe0:
cbuf[off++] = (char) (((val & 0x0f) << 12)
| ((is.read() & 0x3f) << 6) | (is.read() & 0x3f));
break;
case 0xf0: // UCS-4 character
throw new UnsupportedEncodingException("UTF-32 (or UCS-4) encoding not supported.");
default:
cbuf[off++] = (char) val;
break;
}
num++;
}
return num;
}
/**
* Reads a single character.
*
* @return The character read, as an integer in the range 0 to 65535
* (0x00-0xffff), or -1 if the end of the stream has been reached.
* @exception IOException If any IO errors occur.
* @exception UnsupportedEncodingException If UCS-4 character occur in the stream.
*/
public int read() throws IOException {
int val;
if ((val = is.read()) < 0) {
return -1;
}
switch (val & 0xf0) {
case 0xc0:
case 0xd0:
val = ((val & 0x1f) << 6) | (is.read() & 0x3f);
break;
case 0xe0:
val = ((val & 0x0f) << 12)
| ((is.read() & 0x3f) << 6) | (is.read() & 0x3f);
break;
case 0xf0: // UCS-4 character
throw new UnsupportedEncodingException();
default:
break;
}
return val;
}
/**
* Closes the stream.
*
* @exception IOException If any IO errors occur.
*/
public void close() throws IOException {
is.close();
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import java.io.IOException;
import java.io.InputStream;
import jdk.internal.org.xml.sax.InputSource;
import jdk.internal.org.xml.sax.SAXException;
import jdk.internal.org.xml.sax.XMLReader;
import jdk.internal.org.xml.sax.helpers.DefaultHandler;
import jdk.internal.util.xml.SAXParser;
public class SAXParserImpl extends SAXParser {
private ParserSAX parser;
public SAXParserImpl() {
super();
parser = new ParserSAX();
}
/**
* Returns the {@link org.xml.sax.XMLReader} that is encapsulated by the
* implementation of this class.
*
* @return The XMLReader that is encapsulated by the
* implementation of this class.
*
* @throws SAXException If any SAX errors occur during processing.
*/
public XMLReader getXMLReader()
throws SAXException {
return parser;
}
/**
* Indicates whether or not this parser is configured to
* understand namespaces.
*
* @return true if this parser is configured to
* understand namespaces; false otherwise.
*/
public boolean isNamespaceAware() {
return parser.mIsNSAware;
}
/**
* Indicates whether or not this parser is configured to validate
* XML documents.
*
* @return true if this parser is configured to validate XML
* documents; false otherwise.
*/
public boolean isValidating() {
return false;
}
/**
* Parse the content of the given {@link java.io.InputStream}
* instance as XML using the specified
* {@link org.xml.sax.helpers.DefaultHandler}.
*
* @param src InputStream containing the content to be parsed.
* @param handler The SAX DefaultHandler to use.
* @exception IOException If any IO errors occur.
* @exception IllegalArgumentException If the given InputStream or handler is null.
* @exception SAXException If the underlying parser throws a
* SAXException while parsing.
* @see org.xml.sax.helpers.DefaultHandler
*/
public void parse(InputStream src, DefaultHandler handler)
throws SAXException, IOException
{
parser.parse(src, handler);
}
/**
* Parse the content given {@link org.xml.sax.InputSource}
* as XML using the specified
* {@link org.xml.sax.helpers.DefaultHandler}.
*
* @param is The InputSource containing the content to be parsed.
* @param handler The SAX DefaultHandler to use.
* @exception IOException If any IO errors occur.
* @exception IllegalArgumentException If the InputSource or handler is null.
* @exception SAXException If the underlying parser throws a
* SAXException while parsing.
* @see org.xml.sax.helpers.DefaultHandler
*/
public void parse(InputSource is, DefaultHandler handler)
throws SAXException, IOException
{
parser.parse(is, handler);
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import jdk.internal.util.xml.XMLStreamException;
import jdk.internal.util.xml.XMLStreamWriter;
/**
* Implementation of a reduced version of XMLStreamWriter
*
* @author Joe Wang
*/
public class XMLStreamWriterImpl implements XMLStreamWriter {
//Document state
static final int STATE_XML_DECL = 1;
static final int STATE_PROLOG = 2;
static final int STATE_DTD_DECL = 3;
static final int STATE_ELEMENT = 4;
//Element state
static final int ELEMENT_STARTTAG_OPEN = 10;
static final int ELEMENT_STARTTAG_CLOSE = 11;
static final int ELEMENT_ENDTAG_OPEN = 12;
static final int ELEMENT_ENDTAG_CLOSE = 13;
public static final char CLOSE_START_TAG = '>';
public static final char OPEN_START_TAG = '<';
public static final String OPEN_END_TAG = "</";
public static final char CLOSE_END_TAG = '>';
public static final String START_CDATA = "<![CDATA[";
public static final String END_CDATA = "]]>";
public static final String CLOSE_EMPTY_ELEMENT = "/>";
public static final String ENCODING_PREFIX = "&#x";
public static final char SPACE = ' ';
public static final char AMPERSAND = '&';
public static final char DOUBLEQUOT = '"';
public static final char SEMICOLON = ';';
//current state
private int _state = 0;
private Element _currentEle;
private XMLWriter _writer;
private String _encoding;
/**
* This flag can be used to turn escaping off for content. It does
* not apply to attribute content.
*/
boolean _escapeCharacters = true;
//pretty print by default
private boolean _doIndent = true;
//The system line separator for writing out line breaks.
private char[] _lineSep =
System.getProperty("line.separator").toCharArray();
public XMLStreamWriterImpl(OutputStream os) throws XMLStreamException {
this(os, XMLStreamWriter.DEFAULT_ENCODING);
}
public XMLStreamWriterImpl(OutputStream os, String encoding)
throws XMLStreamException
{
Charset cs = null;
if (encoding == null) {
_encoding = XMLStreamWriter.DEFAULT_ENCODING;
} else {
try {
cs = getCharset(encoding);
} catch (UnsupportedEncodingException e) {
throw new XMLStreamException(e);
}
this._encoding = encoding;
}
_writer = new XMLWriter(os, encoding, cs);
}
/**
* Write the XML Declaration. Defaults the XML version to 1.0, and the
* encoding to utf-8.
*
* @throws XMLStreamException
*/
public void writeStartDocument() throws XMLStreamException {
writeStartDocument(_encoding, XMLStreamWriter.DEFAULT_XML_VERSION);
}
/**
* Write the XML Declaration. Defaults the encoding to utf-8
*
* @param version version of the xml document
* @throws XMLStreamException
*/
public void writeStartDocument(String version) throws XMLStreamException {
writeStartDocument(_encoding, version, null);
}
/**
* Write the XML Declaration. Note that the encoding parameter does not set
* the actual encoding of the underlying output. That must be set when the
* instance of the XMLStreamWriter is created
*
* @param encoding encoding of the xml declaration
* @param version version of the xml document
* @throws XMLStreamException If given encoding does not match encoding of the
* underlying stream
*/
public void writeStartDocument(String encoding, String version) throws XMLStreamException {
writeStartDocument(encoding, version, null);
}
/**
* Write the XML Declaration. Note that the encoding parameter does not set
* the actual encoding of the underlying output. That must be set when the
* instance of the XMLStreamWriter is created
*
* @param encoding encoding of the xml declaration
* @param version version of the xml document
* @param standalone indicate if the xml document is standalone
* @throws XMLStreamException If given encoding does not match encoding of the
* underlying stream
*/
public void writeStartDocument(String encoding, String version, String standalone)
throws XMLStreamException
{
if (_state > 0) {
throw new XMLStreamException("XML declaration must be as the first line in the XML document.");
}
_state = STATE_XML_DECL;
String enc = encoding;
if (enc == null) {
enc = _encoding;
} else {
//check if the encoding is supported
try {
getCharset(encoding);
} catch (UnsupportedEncodingException e) {
throw new XMLStreamException(e);
}
}
if (version == null) {
version = XMLStreamWriter.DEFAULT_XML_VERSION;
}
_writer.write("<?xml version=\"");
_writer.write(version);
_writer.write(DOUBLEQUOT);
if (enc != null) {
_writer.write(" encoding=\"");
_writer.write(enc);
_writer.write(DOUBLEQUOT);
}
if (standalone != null) {
_writer.write(" standalone=\"");
_writer.write(standalone);
_writer.write(DOUBLEQUOT);
}
_writer.write("?>");
writeLineSeparator();
}
/**
* Write a DTD section. This string represents the entire doctypedecl production
* from the XML 1.0 specification.
*
* @param dtd the DTD to be written
* @throws XMLStreamException
*/
public void writeDTD(String dtd) throws XMLStreamException {
if (_currentEle != null && _currentEle.getState() == ELEMENT_STARTTAG_OPEN) {
closeStartTag();
}
_writer.write(dtd);
writeLineSeparator();
}
/**
* Writes a start tag to the output.
* @param localName local name of the tag, may not be null
* @throws XMLStreamException
*/
public void writeStartElement(String localName) throws XMLStreamException {
if (localName == null || localName.length() == 0) {
throw new XMLStreamException("Local Name cannot be null or empty");
}
_state = STATE_ELEMENT;
if (_currentEle != null && _currentEle.getState() == ELEMENT_STARTTAG_OPEN) {
closeStartTag();
}
_currentEle = new Element(_currentEle, localName, false);
openStartTag();
_writer.write(localName);
}
/**
* Writes an empty element tag to the output
* @param localName local name of the tag, may not be null
* @throws XMLStreamException
*/
public void writeEmptyElement(String localName) throws XMLStreamException {
if (_currentEle != null && _currentEle.getState() == ELEMENT_STARTTAG_OPEN) {
closeStartTag();
}
_currentEle = new Element(_currentEle, localName, true);
openStartTag();
_writer.write(localName);
}
/**
* Writes an attribute to the output stream without a prefix.
* @param localName the local name of the attribute
* @param value the value of the attribute
* @throws IllegalStateException if the current state does not allow Attribute writing
* @throws XMLStreamException
*/
public void writeAttribute(String localName, String value) throws XMLStreamException {
if (_currentEle.getState() != ELEMENT_STARTTAG_OPEN) {
throw new XMLStreamException(
"Attribute not associated with any element");
}
_writer.write(SPACE);
_writer.write(localName);
_writer.write("=\"");
writeXMLContent(
value,
true, // true = escapeChars
true); // true = escapeDoubleQuotes
_writer.write(DOUBLEQUOT);
}
public void writeEndDocument() throws XMLStreamException {
if (_currentEle != null && _currentEle.getState() == ELEMENT_STARTTAG_OPEN) {
closeStartTag();
}
/**
* close unclosed elements if any
*/
while (_currentEle != null) {
if (!_currentEle.isEmpty()) {
_writer.write(OPEN_END_TAG);
_writer.write(_currentEle.getLocalName());
_writer.write(CLOSE_END_TAG);
}
_currentEle = _currentEle.getParent();
}
}
public void writeEndElement() throws XMLStreamException {
if (_currentEle != null && _currentEle.getState() == ELEMENT_STARTTAG_OPEN) {
closeStartTag();
}
if (_currentEle == null) {
throw new XMLStreamException("No element was found to write");
}
if (_currentEle.isEmpty()) {
return;
}
_writer.write(OPEN_END_TAG);
_writer.write(_currentEle.getLocalName());
_writer.write(CLOSE_END_TAG);
writeLineSeparator();
_currentEle = _currentEle.getParent();
}
public void writeCData(String cdata) throws XMLStreamException {
if (cdata == null) {
throw new XMLStreamException("cdata cannot be null");
}
if (_currentEle != null && _currentEle.getState() == ELEMENT_STARTTAG_OPEN) {
closeStartTag();
}
_writer.write(START_CDATA);
_writer.write(cdata);
_writer.write(END_CDATA);
}
public void writeCharacters(String data) throws XMLStreamException {
if (_currentEle != null && _currentEle.getState() == ELEMENT_STARTTAG_OPEN) {
closeStartTag();
}
writeXMLContent(data);
}
public void writeCharacters(char[] data, int start, int len)
throws XMLStreamException {
if (_currentEle != null && _currentEle.getState() == ELEMENT_STARTTAG_OPEN) {
closeStartTag();
}
writeXMLContent(data, start, len, _escapeCharacters);
}
/**
* Close this XMLStreamWriter by closing underlying writer.
*/
public void close() throws XMLStreamException {
if (_writer != null) {
_writer.close();
}
_writer = null;
_currentEle = null;
_state = 0;
}
/**
* Flush this XMLStreamWriter by flushing underlying writer.
*/
public void flush() throws XMLStreamException {
if (_writer != null) {
_writer.flush();
}
}
/**
* Set the flag to indicate if the writer should add line separator
* @param doIndent
*/
public void setDoIndent(boolean doIndent) {
_doIndent = doIndent;
}
/**
* Writes XML content to underlying writer. Escapes characters unless
* escaping character feature is turned off.
*/
private void writeXMLContent(char[] content, int start, int length, boolean escapeChars)
throws XMLStreamException
{
if (!escapeChars) {
_writer.write(content, start, length);
return;
}
// Index of the next char to be written
int startWritePos = start;
final int end = start + length;
for (int index = start; index < end; index++) {
char ch = content[index];
if (!_writer.canEncode(ch)) {
_writer.write(content, startWritePos, index - startWritePos);
// Escape this char as underlying encoder cannot handle it
_writer.write(ENCODING_PREFIX);
_writer.write(Integer.toHexString(ch));
_writer.write(SEMICOLON);
startWritePos = index + 1;
continue;
}
switch (ch) {
case OPEN_START_TAG:
_writer.write(content, startWritePos, index - startWritePos);
_writer.write("&lt;");
startWritePos = index + 1;
break;
case AMPERSAND:
_writer.write(content, startWritePos, index - startWritePos);
_writer.write("&amp;");
startWritePos = index + 1;
break;
case CLOSE_START_TAG:
_writer.write(content, startWritePos, index - startWritePos);
_writer.write("&gt;");
startWritePos = index + 1;
break;
}
}
// Write any pending data
_writer.write(content, startWritePos, end - startWritePos);
}
private void writeXMLContent(String content) throws XMLStreamException {
if ((content != null) && (content.length() > 0)) {
writeXMLContent(content,
_escapeCharacters, // boolean = escapeChars
false); // false = escapeDoubleQuotes
}
}
/**
* Writes XML content to underlying writer. Escapes characters unless
* escaping character feature is turned off.
*/
private void writeXMLContent(
String content,
boolean escapeChars,
boolean escapeDoubleQuotes)
throws XMLStreamException
{
if (!escapeChars) {
_writer.write(content);
return;
}
// Index of the next char to be written
int startWritePos = 0;
final int end = content.length();
for (int index = 0; index < end; index++) {
char ch = content.charAt(index);
if (!_writer.canEncode(ch)) {
_writer.write(content, startWritePos, index - startWritePos);
// Escape this char as underlying encoder cannot handle it
_writer.write(ENCODING_PREFIX);
_writer.write(Integer.toHexString(ch));
_writer.write(SEMICOLON);
startWritePos = index + 1;
continue;
}
switch (ch) {
case OPEN_START_TAG:
_writer.write(content, startWritePos, index - startWritePos);
_writer.write("&lt;");
startWritePos = index + 1;
break;
case AMPERSAND:
_writer.write(content, startWritePos, index - startWritePos);
_writer.write("&amp;");
startWritePos = index + 1;
break;
case CLOSE_START_TAG:
_writer.write(content, startWritePos, index - startWritePos);
_writer.write("&gt;");
startWritePos = index + 1;
break;
case DOUBLEQUOT:
_writer.write(content, startWritePos, index - startWritePos);
if (escapeDoubleQuotes) {
_writer.write("&quot;");
} else {
_writer.write(DOUBLEQUOT);
}
startWritePos = index + 1;
break;
}
}
// Write any pending data
_writer.write(content, startWritePos, end - startWritePos);
}
/**
* marks open of start tag and writes the same into the writer.
*/
private void openStartTag() throws XMLStreamException {
_currentEle.setState(ELEMENT_STARTTAG_OPEN);
_writer.write(OPEN_START_TAG);
}
/**
* marks close of start tag and writes the same into the writer.
*/
private void closeStartTag() throws XMLStreamException {
if (_currentEle.isEmpty()) {
_writer.write(CLOSE_EMPTY_ELEMENT);
} else {
_writer.write(CLOSE_START_TAG);
}
if (_currentEle.getParent() == null) {
writeLineSeparator();
}
_currentEle.setState(ELEMENT_STARTTAG_CLOSE);
}
/**
* Write a line separator
* @throws XMLStreamException
*/
private void writeLineSeparator() throws XMLStreamException {
if (_doIndent) {
_writer.write(_lineSep, 0, _lineSep.length);
}
}
/**
* Returns a charset object for the specified encoding
* @param encoding
* @return a charset object
* @throws UnsupportedEncodingException if the encoding is not supported
*/
private Charset getCharset(String encoding) throws UnsupportedEncodingException {
if (encoding.equalsIgnoreCase("UTF-32")) {
throw new UnsupportedEncodingException("The basic XMLWriter does "
+ "not support " + encoding);
}
Charset cs;
try {
cs = Charset.forName(encoding);
} catch (IllegalCharsetNameException | UnsupportedCharsetException ex) {
throw new UnsupportedEncodingException(encoding);
}
return cs;
}
/*
* Start of Internal classes.
*
*/
protected class Element {
/**
* the parent element
*/
protected Element _parent;
/**
* The size of the stack.
*/
protected short _Depth;
/**
* indicate if an element is an empty one
*/
boolean _isEmptyElement = false;
String _localpart;
int _state;
/**
* Default constructor.
*/
public Element() {
}
/**
* @param parent the parent of the element
* @param localpart name of the element
* @param isEmpty indicate if the element is an empty one
*/
public Element(Element parent, String localpart, boolean isEmpty) {
_parent = parent;
_localpart = localpart;
_isEmptyElement = isEmpty;
}
public Element getParent() {
return _parent;
}
public String getLocalName() {
return _localpart;
}
/**
* get the state of the element
*/
public int getState() {
return _state;
}
/**
* Set the state of the element
*
* @param state the state of the element
*/
public void setState(int state) {
_state = state;
}
public boolean isEmpty() {
return _isEmptyElement;
}
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util.xml.impl;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import jdk.internal.util.xml.XMLStreamException;
/**
*
* @author huizwang
*/
public class XMLWriter {
private Writer _writer;
/**
* In some cases, this charset encoder is used to determine if a char is
* encodable by underlying writer. For example, an 8-bit char from the
* extended ASCII set is not encodable by 7-bit ASCII encoder. Unencodable
* chars are escaped using XML numeric entities.
*/
private CharsetEncoder _encoder = null;
public XMLWriter(OutputStream os, String encoding, Charset cs) throws XMLStreamException {
_encoder = cs.newEncoder();
try {
_writer = getWriter(os, encoding, cs);
} catch (UnsupportedEncodingException ex) {
throw new XMLStreamException(ex);
}
}
public boolean canEncode(char ch) {
if (_encoder == null) {
return false;
}
return (_encoder.canEncode(ch));
}
public void write(String s)
throws XMLStreamException {
try {
_writer.write(s.toCharArray());
// _writer.write(s.getBytes(Charset.forName(_encoding)));
} catch (IOException e) {
throw new XMLStreamException("I/O error", e);
}
}
public void write(String str, int off, int len)
throws XMLStreamException {
try {
_writer.write(str, off, len);
} catch (IOException e) {
throw new XMLStreamException("I/O error", e);
}
}
public void write(char[] cbuf, int off, int len)
throws XMLStreamException {
try {
_writer.write(cbuf, off, len);
} catch (IOException e) {
throw new XMLStreamException("I/O error", e);
}
}
void write(int b)
throws XMLStreamException {
try {
_writer.write(b);
} catch (IOException e) {
throw new XMLStreamException("I/O error", e);
}
}
void flush() throws XMLStreamException {
try {
_writer.flush();
} catch (IOException ex) {
throw new XMLStreamException(ex);
}
}
void close() throws XMLStreamException {
try {
_writer.close();
} catch (IOException ex) {
throw new XMLStreamException(ex);
}
}
private void nl() throws XMLStreamException {
String lineEnd = System.getProperty("line.separator");
try {
_writer.write(lineEnd);
} catch (IOException e) {
throw new XMLStreamException("I/O error", e);
}
}
/**
* Returns a writer for the specified encoding based on an output stream.
*
* @param output The output stream
* @param encoding The encoding
* @return A suitable writer
* @throws UnsupportedEncodingException There is no convertor to support
* this encoding
*/
private Writer getWriter(OutputStream output, String encoding, Charset cs)
throws XMLStreamException, UnsupportedEncodingException
{
if (cs != null) {
return (new OutputStreamWriter(new BufferedOutputStream(output), cs));
}
return new OutputStreamWriter(new BufferedOutputStream(output), encoding);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册