--- old/make/jdk/Makefile 2012-12-05 14:31:03.000000000 +0000 +++ new/make/jdk/Makefile 2012-12-05 14:31:02.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -23,16 +23,18 @@ # questions. # -# -# Makefile for building all of java -# - BUILDDIR = .. +PACKAGE = jdk PRODUCT = jdk +JAVAC_LINT_OPTIONS=-Xlint:all include $(BUILDDIR)/common/Defs.gmk -SUBDIRS = asm -include $(BUILDDIR)/common/Subdirs.gmk +# +# Files to compile +# +AUTO_FILES_JAVA_DIRS = jdk -all build clean clobber:: - $(SUBDIRS-loop) +# +# Rules +# +include $(BUILDDIR)/common/Classes.gmk --- old/src/share/classes/java/util/Properties.java 2012-12-05 14:31:04.000000000 +0000 +++ new/src/share/classes/java/util/Properties.java 2012-12-05 14:31:04.000000000 +0000 @@ -1188,7 +1188,7 @@ provider = loadProviderAsService(cl); if (provider != null) return provider; - throw new InternalError("No fallback"); + return new jdk.internal.util.xml.BasicXmlPropertiesProvider(); }}); } --- old/test/java/util/Properties/LoadAndStoreXML.java 2012-12-05 14:31:06.000000000 +0000 +++ new/test/java/util/Properties/LoadAndStoreXML.java 2012-12-05 14:31:05.000000000 +0000 @@ -23,8 +23,10 @@ /* * @test - * @bug 8000354 8000685 + * @bug 8000354 8000685 8004371 * @summary Basic test of storeToXML and loadToXML + * @run main LoadAndStoreXML + * @run main/othervm -Dsun.util.spi.XmlPropertiesProvider=jdk.internal.util.xml.BasicXmlPropertiesProvider LoadAndStoreXML */ import java.io.*; --- /dev/null 2012-12-05 14:31:08.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/Attributes.java 2012-12-05 14:31:07.000000000 +0000 @@ -0,0 +1,281 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

This interface allows access to a list of attributes in + * three different ways:

+ * + *
    + *
  1. by attribute index;
  2. + *
  3. by Namespace-qualified name; or
  4. + *
  5. by qualified (prefixed) name.
  6. + *
+ * + *

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 http://xml.org/sax/features/namespace-prefixes + * feature is set to true (it is false by + * default). + * Because SAX2 conforms to the original "Namespaces in XML" + * recommendation, it normally does not + * give namespace declaration attributes a namespace URI. + *

+ * + *

Some SAX2 parsers may support using an optional feature flag + * (http://xml.org/sax/features/xmlns-uris) 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.

+ * + *

If the namespace-prefixes feature (see above) is + * false, access by qualified name may not be available; if + * the http://xml.org/sax/features/namespaces feature is + * false, access by Namespace-qualified names may not be + * available.

+ * + *

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 getIndex methods (below).

+ * + *

The order of attributes in the list is unspecified, and will + * vary from implementation to implementation.

+ * + * @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. + * + *

Once you know the number of attributes, you can iterate + * through the list.

+ * + * @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. + * + *

The attribute type is one of the strings "CDATA", "ID", + * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", + * or "NOTATION" (always in upper case).

+ * + *

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").

+ * + *

For an enumerated attribute that is not a notation, the + * parser will report the type as "NMTOKEN".

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

See {@link #getType(int) getType(int)} for a description + * of the possible types.

+ * + * @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. + * + *

See {@link #getType(int) getType(int)} for a description + * of the possible types.

+ * + * @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. + * + *

See {@link #getValue(int) getValue(int)} for a description + * of the possible values.

+ * + * @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. + * + *

See {@link #getValue(int) getValue(int)} for a description + * of the possible values.

+ * + * @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 --- /dev/null 2012-12-05 14:31:09.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/ContentHandler.java 2012-12-05 14:31:08.000000000 +0000 @@ -0,0 +1,443 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + *

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.

+ * + *

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).

+ * + *

Implementors should note that there is also a + * ContentHandler class in the java.net + * package; that means that it's probably a bad idea to do

+ * + *
import java.net.*;
+ * import org.xml.sax.*;
+ * 
+ * + *

In fact, "import ...*" is usually a sign of sloppy programming + * anyway, so the user should consider this a feature rather than a + * bug.

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + *

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.

+ * + * @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. + * + *

The SAX parser will invoke this method only once, before any + * other event callbacks (except for {@link #setDocumentLocator + * setDocumentLocator}).

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + * @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. + * + *

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 http://xml.org/sax/features/namespaces + * feature is true (the default).

+ * + *

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.

+ * + *

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.

+ * + *

There should never be start/endPrefixMapping events for the + * "xml" prefix, since it is predeclared and immutable.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + *

This event allows up to three name components for each + * element:

+ * + *
    + *
  1. the Namespace URI;
  2. + *
  3. the local name; and
  4. + *
  5. the qualified (prefixed) name.
  6. + *
+ * + *

Any or all of these may be provided, depending on the + * values of the http://xml.org/sax/features/namespaces + * and the http://xml.org/sax/features/namespace-prefixes + * properties:

+ * + * + * + *

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 + * http://xml.org/sax/features/namespace-prefixes + * property is true (it is false by default, and support for a + * true value is optional).

+ * + *

Like {@link #characters characters()}, attribute values may have + * characters that need more than one char value.

+ * + * @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. + * + *

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).

+ * + *

For information on the names, see startElement.

+ * + * @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. + * + *

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.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + *

Individual characters may consist of more than one Java + * char 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 Surrogate Pair, + * 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.

+ * + *

Your code should not assume that algorithms using + * char-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.

+ * + *

Note that some parsers will report whitespace in element + * content using the {@link #ignorableWhitespace ignorableWhitespace} + * method rather than this one (validating parsers must + * do so).

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + *

The application must not attempt to read from the array + * outside of the specified range.

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + *

Like {@link #characters characters()}, processing instruction + * data may have characters that need more than one char + * value.

+ * + * @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.) + * + *

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 + * http://xml.org/sax/features/external-general-entities + * and the + * http://xml.org/sax/features/external-parameter-entities + * properties.

+ * + * @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 --- /dev/null 2012-12-05 14:31:10.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/DTDHandler.java 2012-12-05 14:31:10.000000000 +0000 @@ -0,0 +1,141 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + *

Note that this interface includes only those DTD events that + * the XML recommendation requires processors to report: + * notation and unparsed entity declarations.

+ * + *

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.) + *

+ * + *

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.

+ * + * @since SAX 1.0 + * @author David Megginson + * @see org.xml.sax.XMLReader#setDTDHandler + */ +public interface DTDHandler { + + + /** + * Receive notification of a notation declaration event. + * + *

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.

+ * + *

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.

+ * + *

There is no guarantee that the notation declaration will be + * reported before any unparsed entities that use it.

+ * + * @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. + * + *

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. + *

+ * + *

If the system identifier is a URL, the parser must resolve it + * fully before passing it to the application.

+ * + * @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 --- /dev/null 2012-12-05 14:31:11.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/EntityResolver.java 2012-12-05 14:31:11.000000000 +0000 @@ -0,0 +1,143 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + *

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.

+ * + *

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.

+ * + *

The following resolver would provide the application + * with a special character stream for the entity with the system + * identifier "http://www.myhost.com/today":

+ * + *
+ * 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;
+ *     }
+ *   }
+ * }
+ * 
+ * + *

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).

+ * + * @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. + * + *

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).

+ * + *

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.

+ * + *

If the system identifier is a URL, the SAX parser must + * resolve it fully before reporting it to the application.

+ * + * @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 --- /dev/null 2012-12-05 14:31:12.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/ErrorHandler.java 2012-12-05 14:31:12.000000000 +0000 @@ -0,0 +1,163 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + *

WARNING: If an application does not + * register an ErrorHandler, XML parsing errors will go unreported, + * except that SAXParseExceptions 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.

+ * + *

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.

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + *

Filters may use this method to report other, non-XML warnings + * as well.

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + *

Filters may use this method to report other, non-XML errors + * as well.

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + *

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.

+ * + * @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 --- /dev/null 2012-12-05 14:31:13.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/InputSource.java 2012-12-05 14:31:13.000000000 +0000 @@ -0,0 +1,360 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + *

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.

+ * + *

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.

+ * + *

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.

+ * + * @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. + * + *

Applications may use setPublicId to include a + * public identifier as well, or setEncoding to specify + * the character encoding, if known.

+ * + *

If the system identifier is a URL, it must be fully + * resolved (it may not be a relative URL).

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

Application writers should use setSystemId() to provide a base + * for resolving relative URIs, and may use setPublicId to include a + * public identifier.

+ * + *

The character stream shall not include a byte order mark.

+ * + * @see #setPublicId + * @see #setSystemId + * @see #setByteStream + * @see #setCharacterStream + */ + public InputSource (Reader characterStream) + { + setCharacterStream(characterStream); + } + + + /** + * Set the public identifier for this input source. + * + *

The public identifier is always optional: if the application + * writer includes one, it will be provided as part of the + * location information.

+ * + * @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. + * + *

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).

+ * + *

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.

+ * + *

If the system identifier is a URL, it must be fully + * resolved (it may not be a relative URL).

+ * + * @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. + * + *

The getEncoding method will return the character encoding + * of the object pointed to, or null if unknown.

+ * + *

If the system ID is a URL, it will be fully resolved.

+ * + * @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. + * + *

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.

+ * + *

If the application knows the character encoding of the + * byte stream, it should set it with the setEncoding method.

+ * + * @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. + * + *

The getEncoding method will return the character + * encoding for this byte stream, or null if unknown.

+ * + * @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. + * + *

The encoding must be a string acceptable for an + * XML encoding declaration (see section 4.3.3 of the XML 1.0 + * recommendation).

+ * + *

This method has no effect when the application provides a + * character stream.

+ * + * @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. + * + *

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.

+ * + * @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 --- /dev/null 2012-12-05 14:31:14.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/Locator.java 2012-12-05 14:31:13.000000000 +0000 @@ -0,0 +1,160 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + *

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.

+ * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + *

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 file:... URL, and other + * kinds of relative URI are also resolved against their bases.

+ * + * @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. + * + *

Warning: 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.

+ * + *

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.

+ * + *

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.

+ * + * @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 char values since + * the last line end. + * + *

Warning: 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.

+ * + *

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.

+ * + *

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.

+ * + * @return The column number, or -1 if none is available. + * @see #getLineNumber + */ + public abstract int getColumnNumber (); + +} + +// end of Locator.java --- /dev/null 2012-12-05 14:31:15.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/SAXException.java 2012-12-05 14:31:14.000000000 +0000 @@ -0,0 +1,188 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + *

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.

+ * + *

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.

+ * + * @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. + * + *

The existing exception will be embedded in the new + * one, and its message will become the default message for + * the SAXException.

+ * + * @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. + * + *

The existing exception will be embedded in the new + * one, but the new exception will have its own message.

+ * + * @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. + * + *

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.

+ * + * @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 --- /dev/null 2012-12-05 14:31:17.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/SAXNotRecognizedException.java 2012-12-05 14:31:16.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + * @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 --- /dev/null 2012-12-05 14:31:17.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/SAXNotSupportedException.java 2012-12-05 14:31:17.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + * @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 --- /dev/null 2012-12-05 14:31:19.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/SAXParseException.java 2012-12-05 14:31:18.000000000 +0000 @@ -0,0 +1,313 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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.

+ * + *

Since this exception is a subclass of {@link org.xml.sax.SAXException + * SAXException}, it inherits the ability to wrap another exception.

+ * + * @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. + * + *

This constructor is especially useful when an application is + * creating its own exception from within a {@link org.xml.sax.ContentHandler + * ContentHandler} callback.

+ * + * @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. + * + *

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}.

+ * + * @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. + * + *

This constructor is most useful for parser writers.

+ * + *

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.

+ * + * + * @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. + * + *

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}.

+ * + *

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.

+ * + * @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. + * + *

If the system identifier is a URL, it will have been resolved + * fully.

+ * + * @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. + * + *

The first line is line 1.

+ * + * @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. + * + *

The first column in a line is position 1.

+ * + * @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 --- /dev/null 2012-12-05 14:31:20.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/XMLReader.java 2012-12-05 14:31:19.000000000 +0000 @@ -0,0 +1,428 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

Note: despite its name, this interface does + * not extend the standard Java {@link java.io.Reader Reader} + * interface, because reading XML is a fundamentally different activity + * than reading character data.

+ * + *

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.

+ * + *

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.

+ * + *

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):

+ * + *
    + *
  1. it adds a standard way to query and set features and + * properties; and
  2. + *
  3. it adds Namespace support, which is required for many + * higher-level XML standards.
  4. + *
+ * + *

There are adapters available to convert a SAX1 Parser to + * a SAX2 XMLReader and vice-versa.

+ * + * @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. + * + *

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.)

+ * + *

All XMLReaders are required to recognize the + * http://xml.org/sax/features/namespaces and the + * http://xml.org/sax/features/namespace-prefixes feature names.

+ * + *

Typical usage is something like this:

+ * + *
+     * 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.");
+     * }
+     * 
+ * + *

Implementors are free (and encouraged) to invent their own features, + * using names built on their own URIs.

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + * @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. + * + *

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.

+ * + *

XMLReaders are not required to recognize any specific + * property names, though an initial core set is documented for + * SAX2.

+ * + *

Implementors are free (and encouraged) to invent their own properties, + * using names built on their own URIs.

+ * + * @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. + * + *

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.

+ * + *

XMLReaders are not required to recognize setting + * any specific property names, though a core set is defined by + * SAX2.

+ * + *

This method is also the standard mechanism for setting + * extended handlers.

+ * + * @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. + * + *

If the application does not register an entity resolver, + * the XMLReader will perform its own default resolution.

+ * + *

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.

+ * + * @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. + * + *

If the application does not register a DTD handler, all DTD + * events reported by the SAX parser will be silently ignored.

+ * + *

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.

+ * + * @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. + * + *

If the application does not register a content handler, all + * content events reported by the SAX parser will be silently + * ignored.

+ * + *

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.

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + * @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. + * + *

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).

+ * + *

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.) + *

+ * + *

During the parse, the XMLReader will provide information + * about the XML document through the registered event + * handlers.

+ * + *

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.

+ * + * @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). + * + *

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:

+ * + *
+     * parse(new InputSource(systemId));
+     * 
+ * + *

If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser.

+ * + * @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; + +} --- /dev/null 2012-12-05 14:31:21.000000000 +0000 +++ new/src/share/classes/jdk/internal/org/xml/sax/helpers/DefaultHandler.java 2012-12-05 14:31:21.000000000 +0000 @@ -0,0 +1,491 @@ +/* + * 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. + * + *
+ * This module, both source code and documentation, is in the + * Public Domain, and comes with NO WARRANTY. + * See http://www.saxproject.org + * for further information. + *
+ * + *

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:

+ * + * + * + *

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.

+ * + *

This class replaces the deprecated SAX1 + * {@link org.xml.sax.HandlerBase HandlerBase} class.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to keep track of the unparsed entities + * declared in a document.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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).

+ * + * @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. + * + *

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).

+ * + * @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. + * + *

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).

+ * + * @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. + * + *

By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each prefix mapping.

+ * + * @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. + * + *

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).

+ * + * @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. + * + *

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).

+ * + * @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. + * + *

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).

+ * + * @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. + * + *

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).

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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 --- /dev/null 2012-12-05 14:31:22.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/BasicXmlPropertiesProvider.java 2012-12-05 14:31:22.000000000 +0000 @@ -0,0 +1,59 @@ +/* + * 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.util.Properties; +import java.util.InvalidPropertiesFormatException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +import sun.util.spi.XmlPropertiesProvider; + +/** + * A {@code XmlPropertiesProvider} implementation that uses the UKit XML parser. + */ + +public class BasicXmlPropertiesProvider extends XmlPropertiesProvider { + + private final PropertiesDefaultHandler handler = new PropertiesDefaultHandler(); + + public BasicXmlPropertiesProvider() { } + + @Override + public void load(Properties props, InputStream in) + throws IOException, InvalidPropertiesFormatException + { + handler.load(props, in); + } + + @Override + public void store(Properties props, OutputStream os, String comment, + String encoding) + throws IOException + { + handler.store(props, os, comment, encoding); + } +} --- /dev/null 2012-12-05 14:31:23.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java 2012-12-05 14:31:23.000000000 +0000 @@ -0,0 +1,232 @@ +/* + * 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 jdk.internal.util.xml.impl.XMLStreamWriter; +import jdk.internal.util.xml.impl.XMLStreamWriterImpl; +import jdk.internal.util.xml.impl.XMLStreamException; +import jdk.internal.util.xml.impl.SAXParser; +import jdk.internal.util.xml.impl.SAXParserImp; +import java.io.*; +import java.util.InvalidPropertiesFormatException; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; +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; + +/** + * 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 + */ +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 = + ""; + private static final String PROPS_DTD_URI = + "http://java.sun.com/dtd/properties.dtd"; + private static final String PROPS_DTD = + "" + + "" + + "" + + "" + + "" + + "" + + ""; + /** + * 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 SAXParserImp(); + 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(); + } + Set keys = props.keySet(); + Iterator i = keys.iterator(); + while (i.hasNext()) { + String key = (String) i.next(); + 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 (rootElem == 1 && !rootElm.equalsIgnoreCase(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.equalsIgnoreCase(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.equalsIgnoreCase(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; + } +} --- /dev/null 2012-12-05 14:31:25.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/Attrs.java 2012-12-05 14:31:24.000000000 +0000 @@ -0,0 +1,431 @@ +/* + * 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. + * + *

Once you know the number of attributes, you can iterate through the + * list.

+ * + * @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. + * + *

The attribute type is one of the strings "CDATA", "ID", "IDREF", + * "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", or "NOTATION" + * (always in upper case).

+ * + *

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").

+ * + *

For an enumerated attribute that is not a notation, the parser will + * report the type as "NMTOKEN".

+ * + * @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. + * + *

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.

+ * + * @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. null 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. + * + *

See {@link #getType(int) getType(int)} for a description of the + * possible types.

+ * + * @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. + * + *

See {@link #getType(int) getType(int)} for a description of the + * possible types.

+ * + * @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. + * + *

See {@link #getValue(int) getValue(int)} for a description of the + * possible values.

+ * + * @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. + * + *

See {@link #getValue(int) getValue(int)} for a description of the + * possible values.

+ * + * @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). + * + *

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 qName. + * + * @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. + * + *

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 qName. + * + * @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); + } +} --- /dev/null 2012-12-05 14:31:25.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/Input.java 2012-12-05 14:31:25.000000000 +0000 @@ -0,0 +1,94 @@ +/* + * 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() + { + } +} --- /dev/null 2012-12-05 14:31:27.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/Pair.java 2012-12-05 14:31:26.000000000 +0000 @@ -0,0 +1,132 @@ +/* + * 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; + } +} --- /dev/null 2012-12-05 14:31:28.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/Parser.java 2012-12-05 14:31:27.000000000 +0000 @@ -0,0 +1,3372 @@ +/* + * 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 mEnt; // the entities look up table + private Map 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.
+ * Possible character type values are:
- ' ' for any kind of white + * space character;
- 'a' for any lower case alphabetical character + * value;
- 'A' for any upper case alphabetical character value;
+ * - 'd' for any decimal digit character value;
- 'z' for any + * character less then ' ' except '\t', '\n', '\r';
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.
+ * Possible character type values are:
- 0 for underscore ('_') or any + * lower and upper case alphabetical character value;
- 1 for colon + * (':') character;
- 2 for dash ('-') and dot ('.') or any decimal + * digit character value;
- 3 for any kind of white space character
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 + */ + 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 ( + * mEnt) and parameter + * ( + * mPEnt) entity look up table. + * + * @exception Exception is parser specific exception form panic method. + * @exception IOException + */ + 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 + */ + 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 + */ + 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 + * ( + * mPref) 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. + * + *

att.num carries attribute flags where: 0x1 - attribute is + * declared in DTD (attribute decalration had been read); 0x2 - attribute's + * default value is used.

+ * + * @param att An object which reprecents current attribute. + * @exception Exception is parser specific exception form panic method. + * @exception IOException + */ + 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 + * id 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 '<!' part is read in dispatcher so the method starts + * with first '-' after '<!'. + * + * @exception Exception is parser specific exception form panic method. + */ + private void comm() + throws Exception { + if (mPh == PH_DOC_START) { + mPh = PH_MISC_DTD; // misc before DTD + } // '= 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 '<?' is read in dispatcher so the method starts with + * first character of PI target name after '<?'. + * + * @exception Exception is parser specific exception form panic method. + * @exception IOException + */ + private void pi() + throws Exception { + // '= 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 '<!' part is read in dispatcher so the method starts + * with first '[' after '<!'. + * + * @exception Exception is parser specific exception form panic method. + * @exception IOException + */ + private void cdat() + throws Exception { + // '= 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 + */ + 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:
+ * eqstr := S "=" qstr
+ * qstr := S ("'" string "'") | + * ('"' string '"')
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 null if entity had been + * resolved successfully. + * @exception Exception is parser specific exception form panic method. + * @exception IOException + */ + 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 = (Input) 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 + */ + 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 = (Input) 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 (name.value is a + * String object which represents the attribute prefix). + * @param value The attribute value. + * @return true 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 null. + * @param sysid The system identifier of the entity or null. + */ + 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 ( + * mPref.name) being declared and the Namespace URI ( + * mPref.value) 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 + * InputSource for specified entity or + * null. + * + * @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 + */ + 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 + */ + 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 lt, gt, amp, + * apos, quot. 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. + */ + 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 "= 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:
- ' ' for any kind of white + * space character;
- 'a' for any lower case alphabetical character + * value;
- 'A' for any upper case alphabetical character value;
+ * - 'd' for any decimal digit character value;
- 'z' for any + * character less then ' ' except '\t', '\n', '\r';
- 'X' for any not + * ASCII character;
- 'Z' for EOS character.
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 MUST NOT 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; + } +} --- /dev/null 2012-12-05 14:31:29.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/ParserSAX.java 2012-12-05 14:31:28.000000000 +0000 @@ -0,0 +1,709 @@ +/* + * 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.SAXNotRecognizedException; +import jdk.internal.org.xml.sax.SAXNotSupportedException; +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 Extensible Markup Language (XML) 1.0 and "Namespaces in XML" + * specifications. The API supported by the parser are CLDC + * 1.0 and JSR-280, a + * JavaME subset of JAXP + * and SAX2. + * + * @see org.xml.sax.XMLReader + */ + +/* pkg */ 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. + * + *

If the application does not register a content handler, all content + * events reported by the SAX parser will be silently ignored.

+ * + *

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.

+ * + * @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. + * + *

If the application does not register a DTD handler, all DTD events + * reported by the SAX parser will be silently ignored.

+ * + *

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.

+ * + * @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. + * + *

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.

+ * + *

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.

+ * + * @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. + * + *

If the application does not register an entity resolver, the XMLReader + * will perform its own default resolution.

+ * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + *

If the system identifier is a URL, the parser must resolve it fully + * before passing it to the application.

+ * + * @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). + * + *

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:

+ * + *
+     * parse(new InputSource(systemId));
+     * 
+ * + *

If the system identifier is a URL, it must be fully resolved by the + * application before it is passed to the parser.

+ * + * @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. + * + *

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).

+ * + *

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.

+ * + *

During the parse, the XMLReader will provide information about the XML + * document through the registered event handlers.

+ * + *

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.

+ * + * @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 saxe) { + throw saxe; + } catch (IOException ioe) { + throw ioe; + } catch (RuntimeException rte) { + throw rte; + } 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. + */ + 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 null. + * @param sysid The system identifier of the entity or null. + */ + 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 ( + * mPref.name) being declared and the Namespace URI ( + * mPref.value) 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 + * InputSource for specified entity or + * null. + * + * @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) throws SAXNotRecognizedException, SAXNotSupportedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException { + throw new UnsupportedOperationException("Not supported yet."); + } +} --- /dev/null 2012-12-05 14:31:31.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/ReaderUTF16.java 2012-12-05 14:31:30.000000000 +0000 @@ -0,0 +1,127 @@ +/* + * 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(); + } +} \ No newline at end of file --- /dev/null 2012-12-05 14:31:32.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/ReaderUTF8.java 2012-12-05 14:31:31.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * 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(); + } +} --- /dev/null 2012-12-05 14:31:33.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/SAXParser.java 2012-12-05 14:31:33.000000000 +0000 @@ -0,0 +1,247 @@ +/* + * 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.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.

+ * + * 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.

+ * + * The system property that controls which Factory implementation + * to create is named "javax.xml.parsers.SAXParserFactory". + * 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.

+ * + * As the content is parsed by the underlying parser, methods of the + * given + * {@link org.xml.sax.helpers.DefaultHandler} are called.

+ * + * 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 Jeff Suttor + * @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 { + + /** + *

Protected constructor to prevent instantiation.

+ */ + 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 InputSource 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(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(); + + /** + *

Get the XInclude processing mode for this parser.

+ * + * @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() + + "\"" + ); + } +} --- /dev/null 2012-12-05 14:31:34.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/SAXParserImp.java 2012-12-05 14:31:34.000000000 +0000 @@ -0,0 +1,124 @@ +/* + * 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; + +public class SAXParserImp + extends SAXParser +{ + private ParserSAX parser; + + public SAXParserImp() + { + 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); + } + +} --- /dev/null 2012-12-05 14:31:35.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/XMLStreamException.java 2012-12-05 14:31:35.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * 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 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 { + + /** + * Default constructor + */ + public XMLStreamException() { + super(); + } + + /** + * Construct an exception with the associated message. + * + * @param msg the message to report + */ + public XMLStreamException(String msg) { + super(msg); + } + + /** + * Construct an exception with the associated exception + * + * @param th a nested exception + */ + public XMLStreamException(Throwable th) { + super(th); + } + + /** + * Construct an exception with the associated message and exception + * + * @param th a nested exception + * @param msg the message to report + */ + public XMLStreamException(String msg, Throwable th) { + super(msg, th); + } +} --- /dev/null 2012-12-05 14:31:37.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/XMLStreamWriter.java 2012-12-05 14:31:36.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * 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; + +/** + * 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; + +} --- /dev/null 2012-12-05 14:31:39.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/XMLStreamWriterImpl.java 2012-12-05 14:31:38.000000000 +0000 @@ -0,0 +1,611 @@ +/* + * 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; + +/** + * 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 String START_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 { + if (encoding == null) { + _encoding = XMLStreamWriter.DEFAULT_ENCODING; + } else { + if (!isEncodingSupported(encoding)) { + throw new XMLStreamException( + new UnsupportedEncodingException("The basic XMLWriter does " + + "not support " + encoding)); + } + this._encoding = encoding; + } + + _writer = new XMLWriter(os, encoding); + } + + /** + * 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 { + if (!isEncodingSupported(encoding)) { + throw new XMLStreamException( + new UnsupportedEncodingException("The basic XMLWriter does " + + "not support " + encoding)); + } + } + + if (version == null) { + version = XMLStreamWriter.DEFAULT_XML_VERSION; + } + + _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("<"); + startWritePos = index + 1; + + break; + + case AMPERSAND: + _writer.write(content, startWritePos, index - startWritePos); + _writer.write("&"); + startWritePos = index + 1; + + break; + + case CLOSE_START_TAG: + _writer.write(content, startWritePos, index - startWritePos); + _writer.write(">"); + 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("<"); + startWritePos = index + 1; + + break; + + case AMPERSAND: + _writer.write(content, startWritePos, index - startWritePos); + _writer.write("&"); + startWritePos = index + 1; + + break; + + case CLOSE_START_TAG: + _writer.write(content, startWritePos, index - startWritePos); + _writer.write(">"); + startWritePos = index + 1; + + break; + + case DOUBLEQUOT: + _writer.write(content, startWritePos, index - startWritePos); + if (escapeDoubleQuotes) { + _writer.write("""); + } 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); + } + } + private boolean isEncodingSupported(String encoding) { + if (encoding.equalsIgnoreCase("UTF-32")) { + return false; + } + return true; + } + /* + * 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; + } + } +} --- /dev/null 2012-12-05 14:31:40.000000000 +0000 +++ new/src/share/classes/jdk/internal/util/xml/impl/XMLWriter.java 2012-12-05 14:31:39.000000000 +0000 @@ -0,0 +1,161 @@ +/* + * 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 java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; + +/** + * + * @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) throws XMLStreamException { + Charset cs; + try { + cs = Charset.forName(encoding); + } catch (IllegalCharsetNameException | UnsupportedCharsetException ex) { + throw new XMLStreamException(new UnsupportedEncodingException(encoding)); + } + _encoder = cs.newEncoder(); + try { + _writer = getWriter(os, encoding); + } 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) + throws XMLStreamException, UnsupportedEncodingException { + + Charset cs = Charset.forName(encoding); + if (cs != null) { + return (new OutputStreamWriter(new BufferedOutputStream(output), cs)); + } + + return new OutputStreamWriter(new BufferedOutputStream(output), encoding); + } +} --- old/make/jdk/asm/Makefile 2012-12-05 14:31:40.000000000 +0000 +++ /dev/null 2012-12-05 14:31:41.000000000 +0000 @@ -1,40 +0,0 @@ -# -# Copyright (c) 1995, 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. -# - -BUILDDIR = ../.. -PACKAGE = jdk.internal.org.objectweb.asm -PRODUCT = jdk -JAVAC_LINT_OPTIONS=-Xlint:all -include $(BUILDDIR)/common/Defs.gmk - -# -# Files to compile -# -AUTO_FILES_JAVA_DIRS = jdk/internal/org/objectweb/asm - -# -# Rules -# -include $(BUILDDIR)/common/Classes.gmk