diff options
Diffstat (limited to 'xml')
264 files changed, 55779 insertions, 0 deletions
diff --git a/xml/MODULE_LICENSE_APACHE2 b/xml/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/xml/MODULE_LICENSE_APACHE2 diff --git a/xml/MODULE_LICENSE_BSD_LIKE b/xml/MODULE_LICENSE_BSD_LIKE new file mode 100644 index 0000000..b56941c --- /dev/null +++ b/xml/MODULE_LICENSE_BSD_LIKE @@ -0,0 +1 @@ +For KXML2. diff --git a/xml/MODULE_LICENSE_W3C b/xml/MODULE_LICENSE_W3C new file mode 100644 index 0000000..3f41106 --- /dev/null +++ b/xml/MODULE_LICENSE_W3C @@ -0,0 +1,3 @@ +For org.w3c.dom code. + +See <http://www.w3.org/Consortium/Legal/>. diff --git a/xml/src/main/java/javax/xml/XMLConstants.java b/xml/src/main/java/javax/xml/XMLConstants.java new file mode 100644 index 0000000..88fcdad --- /dev/null +++ b/xml/src/main/java/javax/xml/XMLConstants.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.xml; + +/** + * Defines several standard constants that are often used during XML processing. + * + * @since Android 1.0 + */ +public class XMLConstants { + + /** + * The default namespace prefix. Defined to be the empty string. + */ + public static final String DEFAULT_NS_PREFIX = ""; + + /** + * The SAX feature name for secure processing. Turning on this feature + * might result in a parser rejecting XML documents that are considered + * "insecure" (having a potential for DOS attacks, for example). The + * Android XML parsing implementation currently ignores this feature. + */ + public static final String FEATURE_SECURE_PROCESSING = + "http://javax.xml.XMLConstants/feature/secure-processing"; + + /** + * The namespace URI for the case that no namespace is being used at all. + * Defined to be the empty string. + */ + public static final String NULL_NS_URI = ""; + + /** + * The official Relax-NG namespace URI. + */ + public static final String RELAXNG_NS_URI = + "http://relaxng.org/ns/structure/1.0"; + + /** + * The official XSchema instance namespace URI, as defined by W3C. + */ + public static final String W3C_XML_SCHEMA_INSTANCE_NS_URI = + "http://www.w3.org/2001/XMLSchema-instance"; + + /** + * The official XSchema namespace URI, as defined by W3C. + */ + public static final String W3C_XML_SCHEMA_NS_URI = + "http://www.w3.org/2001/XMLSchema"; + + /** + * The official XPath datatype namespace URI, as defined by W3C. + */ + public static final String W3C_XPATH_DATATYPE_NS_URI = + "http://www.w3.org/2003/11/xpath-datatypes"; + + /** + * The official XML namespace attribute, as defined by W3C. + */ + public static final String XMLNS_ATTRIBUTE = "xmlns"; + + /** + * The official XML namespace attribute URI, as defined by W3C. + */ + public static final String XMLNS_ATTRIBUTE_NS_URI = + "http://www.w3.org/2000/xmlns/"; + + /** + * The official XML DTD namespace URI, as defined by W3C. + */ + public static final String XML_DTD_NS_URI = "http://www.w3.org/TR/REC-xml"; + + /** + * The official XML namespace prefix, as defined by W3C. + */ + public static final String XML_NS_PREFIX = "xml"; + + /** + * The official XML namespace URI, as defined by W3C. + */ + public static final String XML_NS_URI = + "http://www.w3.org/XML/1998/namespace"; + +} diff --git a/xml/src/main/java/javax/xml/package.html b/xml/src/main/java/javax/xml/package.html new file mode 100644 index 0000000..5a4621d --- /dev/null +++ b/xml/src/main/java/javax/xml/package.html @@ -0,0 +1,8 @@ +<html> + <body> + <p> + Provides a utility class with useful XML constants. + </p> + @since Android 1.0 + </body> +</html>
\ No newline at end of file diff --git a/xml/src/main/java/javax/xml/parsers/DocumentBuilder.java b/xml/src/main/java/javax/xml/parsers/DocumentBuilder.java new file mode 100644 index 0000000..6fd6550 --- /dev/null +++ b/xml/src/main/java/javax/xml/parsers/DocumentBuilder.java @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.xml.parsers; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Defines a bridge from XML sources (files, stream etc.) to DOM trees. Can be + * used for easily obtaining a {@link org.w3c.dom.Document} for the input. The + * class itself is abstract. The class {@link DocumentBuilderFactory} is able to + * provide instances (of concrete subclasses known to the system). + * + * @since Android 1.0 + */ +public abstract class DocumentBuilder { + + /** + * Do-nothing constructor. Prevents instantiation. To be overridden by + * concrete subclasses. + * + * @since Android 1.0 + */ + protected DocumentBuilder() { + // Does nothing. + } + + /** + * Queries the DOM implementation this {@code DocumentBuilder} is working + * on. + * + * @return the DOM implementation + * + * @since Android 1.0 + */ + public abstract DOMImplementation getDOMImplementation(); + +// TODO No XSchema support in Android 1.0. Maybe later. +// /** +// * Queries the XML schema used by the DocumentBuilder. +// * +// * @return The XML schema +// * +// * @throws UnsupportedOperationException when the underlying implementation +// * doesn't support XML schemas. +// */ +// public javax.xml.validation.Schema getSchema() throws +// UnsupportedOperationException { +// throw new UnsupportedOperationException(); +// } + + /** + * Queries whether the {@code DocumentBuilder} has namespace support + * enabled. + * + * @return {@code true} if namespaces are turned on, {@code false} + * otherwise. + * + * @since Android 1.0 + */ + public abstract boolean isNamespaceAware(); + + /** + * Queries whether the {@code DocumentBuilder} has validation support + * enabled. + * + * @return {@code true} if validation is turned on, {@code false} otherwise. + * + * @since Android 1.0 + */ + public abstract boolean isValidating(); + + /** + * Queries whether the {@code DocumentBuilder} has XInclude support enabled. + * + * @return {@code true} if XInclude support is turned on, {@code false} + * otherwise. + * + * @throws UnsupportedOperationException if the underlying implementation + * doesn't support XInclude. + * + * @since Android 1.0 + */ + public boolean isXIncludeAware() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Creates a new, empty document, serving as the starting point for a DOM + * tree. + * + * @return the document. + * + * @since Android 1.0 + */ + public abstract Document newDocument(); + + /** + * Parses a given XML file and builds a DOM tree from it. + * + * @param file the file to be parsed. + * @return the document element that represents the root of the DOM tree. + * + * @throws SAXException if the XML parsing fails. + * @throws IOException if an input/output error occurs. + * + * @since Android 1.0 + */ + public Document parse(File file) throws SAXException, IOException { + if (file == null) { + throw new IllegalArgumentException(); + } + + return parse(new BufferedInputStream(new FileInputStream(file), 8192)); + } + + /** + * Parses a given XML input stream and builds a DOM tree from it. + * + * @param stream the stream to be parsed. + * @return the document element that represents the root of the DOM tree. + * + * @throws SAXException if the XML parsing fails. + * @throws IOException if an input/output error occurs. + * + * @since Android 1.0 + */ + public Document parse(InputStream stream) throws SAXException, IOException { + if (stream == null) { + throw new IllegalArgumentException(); + } + + return parse(new InputSource(stream)); + } + + /** + * Parses a given XML input stream and builds a DOM tree from it. + * + * @param stream the stream to be parsed. + * @param systemId the base for resolving relative URIs. + * @return the document element that represents the root of the DOM tree. + * + * @throws SAXException if the XML parsing fails. + * @throws IOException if an input/output error occurs. + * + * @since Android 1.0 + */ + public org.w3c.dom.Document parse(InputStream stream, String systemId) + throws SAXException, IOException { + if (stream == null) { + throw new IllegalArgumentException(); + } + + InputSource source = new InputSource(stream); + source.setSystemId(systemId); + return parse(source); + } + + /** + * Parses an XML input stream from a given URI and builds a DOM tree from + * it. + * + * @param uri the URI to fetch the XML stream from. + * @return the document element that represents the root of the DOM tree. + * + * @throws SAXException if the XML parsing fails. + * @throws IOException if an input/output error occurs. + * + * @since Android 1.0 + */ + public org.w3c.dom.Document parse(String uri) throws SAXException, + IOException { + if (uri == null) { + throw new IllegalArgumentException(); + } + + return parse(new InputSource(uri)); + } + + /** + * Parses an XML input source and builds a DOM tree from it. + * + * @param source the input source to parse. + * @return the document element that represents the root of the DOM tree. + * + * @throws SAXException if the XML parsing fails. + * @throws IOException if an input/output error occurs. + * + * @since Android 1.0 + */ + public abstract org.w3c.dom.Document parse(InputSource source) + throws SAXException, IOException; + + /** + * Resets the DocumentBuilder to the same state is was in after its + * creation. + * + * @since Android 1.0 + */ + public void reset() { + // Do nothing. + } + + /** + * Sets the {@link EntityResolver} used for resolving entities encountered + * during the parse process. Passing {@code null} results in the + * {@code DocumentBuilder}'s own {@code EntityResolver} being used. + * + * @param resolver the {@code EntityResolver} to use, or null for the + * built-in one. + * + * @since Android 1.0 + */ + public abstract void setEntityResolver(EntityResolver resolver); + + /** + * Sets the {@link ErrorHandler} used for dealing with errors encountered + * during the parse process. Passing {@code null} results in the + * {@code DocumentBuilder}'s own {@code ErrorHandler} being used. + * + * @param handler the {@code ErrorHandler} to use, or {@code null} for the + * built-in one. + * + * @since Android 1.0 + */ + public abstract void setErrorHandler(ErrorHandler handler); + +} diff --git a/xml/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java b/xml/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java new file mode 100644 index 0000000..4e186c1 --- /dev/null +++ b/xml/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.xml.parsers; + +import org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl; + +/** + * Provides a factory for {@link DocumentBuilder} instances. The class first + * needs to be instantiated using the {@link #newInstance()} method. The + * instance can be configured as desired. A call to + * {@link #newDocumentBuilder()} then provides a {@code DocumentBuilder} + * instance matching this configuration (if possible). + * + * @since Android 1.0 + */ +public abstract class DocumentBuilderFactory extends Object { + + private boolean coalesce; + + private boolean expandEntityReferences; + + private boolean ignoreComments; + + private boolean ignoreElementContentWhitespace; + + private boolean namespaceAware; + + private boolean validate; + + /** + * Do-nothing constructor. To be overridden by concrete document builders. + * + * @since Android 1.0 + */ + protected DocumentBuilderFactory() { + // Does nothing. + } + + /** + * Queries an attribute from the underlying implementation. + * + * @param name the name of the attribute. + * @return the value of the attribute. + * + * @throws IllegalArgumentException if the argument is unknown to the + * underlying implementation. + * + * @since Android 1.0 + */ + public abstract Object getAttribute(String name) + throws IllegalArgumentException; + + /** + * Queries a feature from the underlying implementation. + * + * @param name The name of the feature. The default Android implementation + * of {@link DocumentBuilder} supports only the following three + * features: + * + * <dl> + * <dt>{@code http://xml.org/sax/features/namespaces}</dt> + * <dd>Queries the state of namespace-awareness.</dd> + * + * <dt> + * {@code http://xml.org/sax/features/namespace-prefixes} + * </dt> + * <dd>Queries the state of namespace prefix processing</dd> + * + * <dt> + * {@code http://xml.org/sax/features/validation} + * </dt> + * <dd>Queries the state of validation.</dd> + * </dl> + * + * Note that despite the ability to query the validation + * feature, there is currently no validating parser available. + * Also note that currently either namespaces or + * namespace prefixes can be enabled, but not both at the same + * time. + * + * @return the status of the feature. + * + * @throws IllegalArgumentException if the feature is unknown to + * the underlying implementation. + * @throws ParserConfigurationException if the feature is + * known, but not supported. + * + * @since Android 1.0 + */ + public abstract boolean getFeature(String name) + throws ParserConfigurationException; + +// TODO No XSchema support in Android 1.0. Maybe later. +// /** +// * Queries the desired XML Schema object. +// * +// * @return The XML Schema object, if it has been set by a call to setSchema, +// * or null otherwise. +// */ +// public javax.xml.validation.Schema getSchema() { +// return schema; +// } + + /** + * Queries whether the factory is configured to deliver parsers that convert + * CDATA nodes to text nodes and melt them with neighboring nodes. This is + * called "coalescing". + * + * @return {@code true} if coalescing is desired, {@code false} otherwise. + * + * @since Android 1.0 + */ + public boolean isCoalescing() { + return coalesce; + } + + /** + * Queries whether the factory is configured to deliver parsers that expand + * entity references. + * + * @return {@code true} if entity expansion is desired, {@code false} + * otherwise. + * + * @since Android 1.0 + */ + public boolean isExpandEntityReferences() { + return expandEntityReferences; + } + + /** + * Queries whether the factory is configured to deliver parsers that ignore + * comments. + * + * @return {@code true} if comment ignorance is desired, {@code false} + * otherwise. + * + * @since Android 1.0 + */ + public boolean isIgnoringComments() { + return ignoreComments; + } + + /** + * Queries whether the factory is configured to deliver parsers that ignore + * whitespace in elements. + * + * @return {@code true} if whitespace ignorance is desired, {@code false} + * otherwise. + * + * @since Android 1.0 + */ + public boolean isIgnoringElementContentWhitespace() { + return ignoreElementContentWhitespace; + } + + /** + * Queries whether the factory is configured to deliver parsers that are + * namespace-aware. + * + * @return {@code true} if namespace-awareness is desired, {@code false} + * otherwise. + * + * @since Android 1.0 + */ + public boolean isNamespaceAware() { + return namespaceAware; + } + + /** + * Queries whether the factory is configured to deliver parsers that are + * validating. + * + * @return {@code true} if validating is desired, {@code false} otherwise. + * + * @since Android 1.0 + */ + public boolean isValidating() { + return validate; + } + + /** + * Queries whether the factory is configured to deliver parsers that are + * XInclude-aware. + * + * @return {@code true} if XInclude-awareness is desired, {@code false} + * otherwise. + * + * @since Android 1.0 + */ + public boolean isXIncludeAware() { + throw new UnsupportedOperationException(); + } + + /** + * Creates a new {@link DocumentBuilder} that matches the current + * configuration of the factory. + * + * @return the DocumentBuilder. + * @throws ParserConfigurationException if no matching + * {@code DocumentBuilder} could be found. + * + * @since Android 1.0 + */ + public abstract DocumentBuilder newDocumentBuilder() + throws ParserConfigurationException; + + /** + * Creates a new DocumentBuilderFactory that can be configured and then be + * used for creating DocumentBuilder objects. The method first checks the + * value of the {@code DocumentBuilderFactory} property. + * If this is non-{@code null}, it is assumed to be the name of a class + * that serves as the factory. The class is instantiated, and the instance + * is returned. If the property value is {@code null}, the system's default + * factory implementation is returned. + * + * @return the DocumentBuilderFactory. + * @throws FactoryConfigurationError if no {@code DocumentBuilderFactory} + * can be created. + * + * @since Android 1.0 + */ + public static DocumentBuilderFactory newInstance() + throws FactoryConfigurationError { + // TODO Properties file and META-INF case missing here. See spec. + String factory = System + .getProperty("javax.xml.parsers.DocumentBuilderFactory"); + if (factory != null) { + try { + return (DocumentBuilderFactory) Class.forName(factory) + .newInstance(); + } catch (Exception ex) { + // Ignore. + } + } + + try { + return new DocumentBuilderFactoryImpl(); + } catch (Exception ex) { + // Ignore. + } + + throw new FactoryConfigurationError( + "Cannot create DocumentBuilderFactory"); + } + + /** + * Sets an attribute in the underlying implementation. + * + * @param name the name of the attribute. + * @param value the value of the attribute. + * + * @throws IllegalArgumentException if the argument is unknown to the + * underlying implementation. + * + * @since Android 1.0 + */ + public abstract void setAttribute(String name, Object value) + throws IllegalArgumentException; + + /** + * Determines whether the factory is configured to deliver parsers that + * convert CDATA nodes to text nodes and melt them with neighboring nodes. + * This is called "coalescing". + * + * @param value turns coalescing on or off. + * + * @since Android 1.0 + */ + public void setCoalescing(boolean value) { + coalesce = value; + } + + /** + * Determines whether the factory is configured to deliver parsers that + * expands entity references. + * + * @param value turns entity reference expansion on or off. + * + * @since Android 1.0 + */ + public void setExpandEntityReferences(boolean value) { + expandEntityReferences = value; + } + + /** + * Sets a feature in the underlying implementation. + * + * @param name the name of the feature. The default Android implementation + * of {@link DocumentBuilder} supports only the following three + * features: + * + * <dl> + * <dt>{@code http://xml.org/sax/features/namespaces}</dt> + * <dd>Sets the state of namespace-awareness.</dd> + * + * <dt> + * {@code http://xml.org/sax/features/namespace-prefixes} + * </dt> + * <dd>Sets the state of namespace prefix processing</dd> + * + * <dt>{@code http://xml.org/sax/features/validation}</dt> + * <dd>Sets the state of validation.</dd> + * </dl> + * + * Note that despite the ability to set the validation + * feature, there is currently no validating parser available. + * Also note that currently either namespaces or + * namespace prefixes can be enabled, but not both at the same + * time. + * + * @param value the value of the feature. + * + * @throws ParserConfigurationException if the feature is unknown to the + * underlying implementation. + * + * @since Android 1.0 + */ + public abstract void setFeature(String name, boolean value) + throws ParserConfigurationException; + + /** + * Determines whether the factory is configured to deliver parsers that + * ignore comments. + * + * @param value turns comment ignorance on or off. + * + * @since Android 1.0 + */ + public void setIgnoringComments(boolean value) { + ignoreComments = value; + } + + /** + * Determines whether the factory is configured to deliver parsers that + * ignores element whitespace. + * + * @param value turns element whitespace ignorance on or off. + * + * @since Android 1.0 + */ + public void setIgnoringElementContentWhitespace(boolean value) { + ignoreElementContentWhitespace = value; + } + + /** + * Determines whether the factory is configured to deliver parsers that are + * namespace-aware. + * + * @param value turns namespace-awareness on or off. + * + * @since Android 1.0 + */ + public void setNamespaceAware(boolean value) { + namespaceAware = value; + } + +// TODO No XSchema support in Android 1.0. Maybe later. +// /** +// * Sets the desired XML Schema object. +// * +// * @param schema The XML Schema object. +// */ +// public void setSchema(Schema schema) { +// this.schema = schema; +// } + + /** + * Determines whether the factory is configured to deliver parsers that are + * validating. + * + * @param value turns validation on or off. + * + * @since Android 1.0 + */ + public void setValidating(boolean value) { + validate = value; + } + + /** + * Determines whether the factory is configured to deliver parsers that are + * XInclude-aware. + * + * @param value turns XInclude-awareness on or off. + * + * @since Android 1.0 + */ + public void setXIncludeAware(boolean value) { + throw new UnsupportedOperationException(); + } + +} diff --git a/xml/src/main/java/javax/xml/parsers/FactoryConfigurationError.java b/xml/src/main/java/javax/xml/parsers/FactoryConfigurationError.java new file mode 100644 index 0000000..f5e0c03 --- /dev/null +++ b/xml/src/main/java/javax/xml/parsers/FactoryConfigurationError.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.xml.parsers; + +/** + * Represents an error that occurred during the configuration of parser factory. + * + * @since Android 1.0 + */ +public class FactoryConfigurationError extends Error { + + /** + * The nested exception that caused this exception. Note that the nested + * exception will be stored in a special attribute, and can be queried using + * the {@link #getException()} method. It does not use the facility the + * {@link Exception} class provides for storing nested exceptions, since the + * XML API predates that facility. + */ + private Exception cause; + + /** + * Creates a new {@code FactoryConfigurationError} with no error message and + * no cause. + * + * @since Android 1.0 + */ + public FactoryConfigurationError() { + super(); + } + + /** + * Creates a new {@code FactoryConfigurationError} with no error message and + * a given cause. + * + * @param cause the cause of the error. Note that the nested exception will + * be stored in a special attribute, and can be queried using the + * {@link #getException()} method. It does not use the facility the + * Exception class provides for storing nested exceptions, since the + * XML API predates that facility. + * + * @since Android 1.0 + */ + public FactoryConfigurationError(Exception cause) { + super(); + this.cause = cause; + } + + /** + * Creates a new {@code FactoryConfigurationError} with a given error + * message and cause. + * + * @param cause the cause of the error. Note that the nested exception will + * be stored in a special attribute, and can be queried using the + * {@link #getException()} method. It does not use the facility the + * {@link Exception} class provides for storing nested exceptions, + * since the XML API predates that facility. + * @param message The error message. + * + * @since Android 1.0 + */ + public FactoryConfigurationError(Exception cause, String message) { + super(message); + this.cause = cause; + } + + /** + * Creates a new {@code FactoryConfigurationError} with a given error + * message and no cause. + * + * @param message the error message. + * + * @since Android 1.0 + */ + public FactoryConfigurationError(String message) { + super(message); + } + + /** + * Returns the cause of the error, in case there is one. + * + * @return the exception that caused the error, or {@code null} if none is + * set. + * + * @since Android 1.0 + */ + public Exception getException() { + return cause; + } + + /** + * Returns the message of the error, in case there is one. + * + * @return the message. If an explicit error message has been assigned to + * the exception, this one is returned. If not, and there is an + * underlying exception (the cause), then the result of invoking + * {@link #toString()} on that object is returned. Otherwise, {@code + * null} is returned. + * + * @since Android 1.0 + */ + public String getMessage() { + String message = super.getMessage(); + + if (message != null) { + return message; + } else if (cause != null) { + return cause.toString(); + } else { + return null; + } + } +} diff --git a/xml/src/main/java/javax/xml/parsers/ParserConfigurationException.java b/xml/src/main/java/javax/xml/parsers/ParserConfigurationException.java new file mode 100644 index 0000000..49875d6 --- /dev/null +++ b/xml/src/main/java/javax/xml/parsers/ParserConfigurationException.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.xml.parsers; + +/** + * Represents an exception that occurred during the configuration of parser. + * + * @since Android 1.0 + */ +public class ParserConfigurationException extends Exception { + + /** + * Creates a new {@code ParserConfigurationException} with no error message. + * + * @since Android 1.0 + */ + public ParserConfigurationException() { + super(); + } + + /** + * Creates a new {@code ParserConfigurationException} with a given error + * message. + * + * @param msg the error message. + * + * @since Android 1.0 + */ + public ParserConfigurationException(String msg) { + super(msg); + } + +} diff --git a/xml/src/main/java/javax/xml/parsers/SAXParser.java b/xml/src/main/java/javax/xml/parsers/SAXParser.java new file mode 100644 index 0000000..73cc0eb --- /dev/null +++ b/xml/src/main/java/javax/xml/parsers/SAXParser.java @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.xml.parsers; + +import org.xml.sax.HandlerBase; +import org.xml.sax.InputSource; +import org.xml.sax.Parser; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Provides a wrapper around a SAX {@link XMLReader}. This abstract + * class only defines the interface, whereas the {@link SAXParserFactory} class + * is used to obtain instances of concrete subclasses. + * + * @since Android 1.0 + */ +public abstract class SAXParser extends java.lang.Object { + + /** + * Do-nothing constructor. Prevents instantiation. To be overridden by + * concrete subclasses. + * + * @since Android 1.0 + */ + protected SAXParser() { + // Does nothing. + } + + /** + * Queries the underlying SAX {@link Parser} object. + * + * @return the SAX {@code Parser}. + * + * @throws SAXException if a problem occurs. + * + * @since Android 1.0 + */ + public abstract Parser getParser() + throws SAXException; + + /** + * Queries a property of the underlying SAX {@link XMLReader}. + * + * @param name the name of the property. + * @return the value of the property. + * + * @throws SAXNotRecognizedException if the property is not known to the + * underlying SAX {@code XMLReader}. + * @throws SAXNotSupportedException if the property is known, but not + * supported by the underlying SAX {@code XMLReader}. + * + * @since Android 1.0 + */ + public abstract Object getProperty(String name) + throws SAXNotRecognizedException, SAXNotSupportedException; + +// TODO No XSchema support in Android 1.0. Maybe later. +// /** +// * Queries the XML Schema used by the underlying XMLReader. +// * +// * @return The XML Schema. +// */ +// public Schema getSchema() { +// return schema; +// } + + /** + * Queries the underlying SAX XMLReader object. + * + * @return the SAX XMLREader. + * + * @throws SAXException if a problem occurs. + * + * @since Android 1.0 + */ + public abstract XMLReader getXMLReader() throws SAXException; + + /** + * Reflects whether this {@code SAXParser} is namespace-aware. + * + * @return {@code true} if the {@code SAXParser} is namespace-aware, or + * {@code false} otherwise. + * + * @since Android 1.0 + */ + public abstract boolean isNamespaceAware(); + + /** + * Reflects whether this {@code SAXParser} is validating. + * + * @return {@code true} if the {@code SAXParser} is validating, or {@code + * false} otherwise. + * + * @since Android 1.0 + */ + public abstract boolean isValidating(); + + /** + * Reflects whether this {@code SAXParser} is XInclude-aware. + * + * @return {@code true} if the {@code SAXParser} is XInclude-aware, or + * {@code false} otherwise. + * + * @throws UnsupportedOperationException if the underlying implementation + * doesn't know about XInclude at all (backwards compatibility). + * + * @since Android 1.0 + */ + public boolean isXIncludeAware() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Parses the given XML file using the given SAX event handler. + * + * @param file the file containing the XML document. + * @param handler the SAX handler. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(File file, HandlerBase handler) throws SAXException, + IOException { + if (file == null) { + throw new IllegalArgumentException("file must not be null"); + } + if (file.isDirectory()) { + throw new IllegalArgumentException("file must not be a directory"); + } + InputSource source = new InputSource("file:" + file.getAbsolutePath()); + parse(source, handler); + } + + /** + * Parses the given XML file using the given SAX event handler. + * + * @param file the file containing the XML document. + * @param handler the SAX handler. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(File file, DefaultHandler handler) throws SAXException, + IOException { + if (file == null) { + throw new IllegalArgumentException("file must not be null"); + } + if (file.isDirectory()) { + throw new IllegalArgumentException("file must not be a directory"); + } + InputSource source = new InputSource("file:" + file.getAbsolutePath()); + parse(source, handler); + } + + /** + * Parses the given XML InputStream using the given SAX event handler. + * + * @param stream the InputStream containing the XML document. + * @param handler the SAX handler. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(InputStream stream, HandlerBase handler) + throws SAXException, IOException { + if (stream == null) { + throw new IllegalArgumentException("stream must not be null"); + } + parse(new InputSource(stream), handler); + } + + /** + * Parses the given XML InputStream using the given SAX event handler and + * system ID. + * + * @param stream the InputStream containing the XML document. + * @param handler the SAX handler. + * @param systemId the system ID. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(InputStream stream, HandlerBase handler, String systemId) + throws SAXException, IOException { + if (stream == null) { + throw new IllegalArgumentException("stream must not be null"); + } + InputSource source = new InputSource(stream); + if (systemId != null) { + source.setSystemId(systemId); + } + parse(source, handler); + } + + /** + * Parses the given XML InputStream using the given SAX event handler. + * + * @param stream the InputStream containing the XML document. + * @param handler the SAX handler. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(InputStream stream, DefaultHandler handler) + throws SAXException, IOException { + parse(new InputSource(stream), handler); + } + + /** + * Parses the given XML InputStream using the given SAX event handler and + * system ID. + * + * @param stream the InputStream containing the XML document. + * @param handler the SAX handler. + * @param systemId the system ID. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(InputStream stream, DefaultHandler handler, + String systemId) throws SAXException, IOException { + if (stream == null) { + throw new IllegalArgumentException("stream must not be null"); + } + InputSource source = new InputSource(stream); + if (systemId != null) { + source.setSystemId(systemId); + } + parse(source, handler); + } + + /** + * Parses the contents of the given URI using the given SAX event handler. + * + * @param uri the URI pointing to the XML document. + * @param handler the SAX handler. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(String uri, HandlerBase handler) throws SAXException, + IOException { + if (uri == null) { + throw new IllegalArgumentException("uri must not be null"); + } + parse(new InputSource(uri), handler); + } + + /** + * Parses the contents of the given URI using the given SAX event handler. + * + * @param uri the URI pointing to the XML document. + * @param handler the SAX handler. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(String uri, DefaultHandler handler) throws SAXException, + IOException { + if (uri == null) { + throw new IllegalArgumentException("uri must not be null"); + } + parse(new InputSource(uri), handler); + } + + /** + * Parses the given SAX {@link InputSource} using the given SAX event + * handler. + * + * @param source the SAX {@code InputSource} containing the XML document. + * @param handler the SAX handler. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(InputSource source, HandlerBase handler) + throws SAXException, IOException { + Parser parser = getParser(); + if (source == null) { + throw new IllegalArgumentException("source must not be null"); + } + + if (handler != null) { + parser.setDocumentHandler(handler); + parser.setDTDHandler(handler); + parser.setEntityResolver(handler); + parser.setErrorHandler(handler); + } + + parser.parse(source); + } + + /** + * Parses the given SAX {@link InputSource} using the given SAX event + * handler. + * + * @param source the SAX {@code InputSource} containing the XML document. + * @param handler the SAX handler. + * + * @throws SAXException if a problem occurs during SAX parsing. + * @throws IOException if a general IO problem occurs. + * + * @since Android 1.0 + */ + public void parse(InputSource source, DefaultHandler handler) + throws SAXException, IOException { + if (source == null) { + throw new IllegalArgumentException("source must not be null"); + } + XMLReader reader = getXMLReader(); + + if (handler != null) { + reader.setContentHandler(handler); + reader.setDTDHandler(handler); + reader.setEntityResolver(handler); + reader.setErrorHandler(handler); + } + + reader.parse(source); + } + + /** + * Resets the {@code SAXParser} to the same state is was in after its + * creation. + * + * @since Android 1.0 + */ + public void reset() { + // Do nothing. + } + + /** + * Sets a property of the underlying SAX {@link XMLReader}. + * + * @param name the name of the property. + * @param value the value of the property. + * + * @throws SAXNotRecognizedException if the property is not known to the + * underlying SAX {@code XMLReader}. + * @throws SAXNotSupportedException if the property is known, but not + * supported by the underlying SAX {@code XMLReader}. + * + * @since Android 1.0 + */ + public abstract void setProperty(String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException; + +} diff --git a/xml/src/main/java/javax/xml/parsers/SAXParserFactory.java b/xml/src/main/java/javax/xml/parsers/SAXParserFactory.java new file mode 100644 index 0000000..ebf0531 --- /dev/null +++ b/xml/src/main/java/javax/xml/parsers/SAXParserFactory.java @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.xml.parsers; + +import org.apache.harmony.xml.parsers.SAXParserFactoryImpl; + +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.SAXException; + +/** + * Provides a factory for {@link SAXParser} instances. The class first needs to + * be instantiated using the {@link #newInstance()} method. The instance can be + * configured as desired. A call to its {@link #newSAXParser()} then provides a + * {@code SAXParser} instance matching this configuration, if possible. + * + * @since Android 1.0 + */ +public abstract class SAXParserFactory { + + private boolean namespaceAware; + + private boolean validating; + + private boolean xincludeAware; + + /** + * Do-nothing constructor. Prevents instantiation. To be overridden by + * concrete subclasses. + * + * @since Android 1.0 + */ + protected SAXParserFactory() { + // Does nothing. + } + + /** + * Queries a feature from the underlying implementation. + * + * @param name The name of the feature. The default Android implementation + * of {@link SAXParser} supports only the following three + * features: + * + * <dl> + * <dt>{@code http://xml.org/sax/features/namespaces}</dt> + * <dd>Queries the state of namespace-awareness.</dd> + * + * <dt> + * {@code http://xml.org/sax/features/namespace-prefixes} + * </dt> + * <dd>Queries the state of namespace prefix processing</dd> + * + * <dt>{@code http://xml.org/sax/features/validation}</dt> + * <dd>Queries the state of validation.</dd> + * </dl> + * + * Note that despite the ability to query the validation + * feature, there is currently no validating parser available. + * Also note that currently either namespaces or + * namespace prefixes can be enabled, but not both at the same + * time. + * + * @return the status of the feature. + * + * @throws ParserConfigurationException if no {@code SAXParser} matching the + * given criteria is available. + * @throws SAXNotRecognizedException if the given feature is not known to + * the underlying implementation. + * @throws SAXNotSupportedException if the given features is known, but not + * supported by the underlying implementation. + * + * @since Android 1.0 + */ + public abstract boolean getFeature(String name) + throws ParserConfigurationException, SAXNotRecognizedException, + SAXNotSupportedException; + +// TODO No XSchema support in Android 1.0. Maybe later. +// /** +// * Queries the desired XML Schema object. +// * +// * @return The XML Schema object, if it has been set by a call to setSchema, +// * or null otherwise. +// */ +// public javax.xml.validation.Schema getSchema() { +// return schema; +// } + + /** + * Queries whether the factory is configured to deliver parsers that are + * namespace-aware. + * + * @return {@code true} if namespace-awareness is desired, {@code false} + * otherwise. + * + * @since Android 1.0 + */ + public boolean isNamespaceAware() { + return namespaceAware; + } + + /** + * Queries whether the factory is configured to deliver parsers that are + * validating. + * + * @return {@code true} if validating is desired, {@code false} otherwise. + * + * @since Android 1.0 + */ + public boolean isValidating() { + return validating; + } + + /** + * Queries whether the factory is configured to deliver parsers that are + * XInclude-aware. + * + * @return {@code true} if XInclude-awareness is desired, {@code false} + * otherwise. + * + * @since Android 1.0 + */ + public boolean isXIncludeAware() { + throw new UnsupportedOperationException(); + } + + /** + * Creates a new {@code SAXParserFactory} that can be configured and then be + * used for creating {@link SAXParser} objects. The method first checks the + * value of the {@code SAXParserFactory} property. If this + * is non-{@code null}, it is assumed to be the name of a class that serves + * as the factory. The class is instantiated, and the instance is returned. + * If the property value is {@code null}, the system's default factory + * implementation is returned. + * + * @return the {@code SAXParserFactory}. + * + * @throws FactoryConfigurationError if no {@code SAXParserFactory} can be + * created. + * + * @since Android 1.0 + */ + public static SAXParserFactory newInstance() + throws FactoryConfigurationError { + // TODO Properties file and META-INF case missing here. See spec. + String factory = System + .getProperty("javax.xml.parsers.SAXParserFactory"); + if (factory != null) { + try { + return (SAXParserFactory) Class.forName(factory).newInstance(); + } catch (Exception ex) { + throw new FactoryConfigurationError(factory); + } + } + + try { + return new SAXParserFactoryImpl(); + } catch (Exception ex) { + // Ignore. + } + + throw new FactoryConfigurationError("Cannot create SAXParserFactory"); + } + + /** + * Creates a new {@link SAXParser} that matches the current configuration of + * the factory. + * + * @return the {@code SAXParser}. + * + * @throws ParserConfigurationException if no matching {@code SAXParser} + * could be found. + * @throws SAXException if creating the {@code SAXParser} failed due to some + * other reason. + * + * @since Android 1.0 + */ + public abstract SAXParser newSAXParser() + throws ParserConfigurationException, SAXException; + + /** + * Sets a feature in the underlying implementation. + * + * @param name the name of the feature. The default Android implementation + * of {@link SAXParser} supports only the following three + * features: + * + * <dl> + * <dt>{@code http://xml.org/sax/features/namespaces}</dt> + * <dd>Sets the state of namespace-awareness.</dd> + * + * <dt> + * {@code http://xml.org/sax/features/namespace-prefixes} + * </dt> + * <dd>Sets the state of namespace prefix processing</dd> + * + * <dt>{@code http://xml.org/sax/features/validation}</dt> + * <dd>Sets the state of validation.</dd> + * </dl> + * + * Note that despite the ability to query the validation + * feature, there is currently no validating parser available. + * Also note that currently either namespaces or + * namespace prefixes can be enabled, but not both at the same + * time. + * + * @param value the status of the feature. + * + * @throws ParserConfigurationException if no {@code SAXParser} matching + * the given criteria is available. + * @throws SAXNotRecognizedException if the given feature is not known to + * the underlying implementation. + * @throws SAXNotSupportedException if the given features is known, but not + * supported by the underlying implementation. + * + * @since Android 1.0 + */ + public abstract void setFeature(String name, boolean value) + throws ParserConfigurationException, SAXNotRecognizedException, + SAXNotSupportedException; + + /** + * Determines whether the factory is configured to deliver parsers that are + * namespace-aware. + * + * @param value turns namespace-awareness on or off. + * + * @since Android 1.0 + */ + public void setNamespaceAware(boolean value) { + namespaceAware = value; + } + +// TODO No XSchema support in Android 1.0. Maybe later. +// /** +// * Sets the desired XML Schema object. +// * +// * @param schema The XML Schema object. +// */ +// public void setSchema(Schema schema) { +// this.schema = schema; +// } + + /** + * Determines whether the factory is configured to deliver parsers that are + * validating. + * + * @param value turns validation on or off. + * + * @since Android 1.0 + */ + public void setValidating(boolean value) { + validating = value; + } + + /** + * Determines whether the factory is configured to deliver parsers that are + * XInclude-aware. + * + * @param value turns XInclude-awareness on or off. + * + * @since Android 1.0 + */ + public void setXIncludeAware(boolean value) { + throw new UnsupportedOperationException(); + } + +} + diff --git a/xml/src/main/java/javax/xml/parsers/package.html b/xml/src/main/java/javax/xml/parsers/package.html new file mode 100644 index 0000000..7e0921d --- /dev/null +++ b/xml/src/main/java/javax/xml/parsers/package.html @@ -0,0 +1,24 @@ +<html> + <body> + <p> + Provides facilities for parsing XML documents and building Document Object + Model (DOM) trees from them. The + {@link javax.xml.parsers.SAXParserFactory} class serves as an entry point + to event-based XML parsing. The + {@link javax.xml.parsers.DocumentBuilderFactory} class is an entry point + for dealing with DOM trees. Both factories are usually configured + before their factory methods are invoked. They then try to create a + {@link javax.xml.parsers.SAXParser} or a + {@link javax.xml.parsers.DocumentBuilder} (respectively) suiting the + application's needs. If none can be found, an Exception is thrown. + </p> + <p> + Note that in order to cater for resource-constrained environments, + Android's XML packages currently only provide DOM Level 2 Core support + and a non-validating parser. This means that (a) the interface for the + various DOM classes might differ from other implementations and (b) + requesting a validating parser will always fail. + </p> + @since Android 1.0 + </body> +</html>
\ No newline at end of file diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatAttributes.java b/xml/src/main/java/org/apache/harmony/xml/ExpatAttributes.java new file mode 100644 index 0000000..ed6cb11 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/ExpatAttributes.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml; + +import org.xml.sax.Attributes; + +/** + * Wraps native attribute array. + */ +abstract class ExpatAttributes implements Attributes { + + /** + * Since we don't do validation, pretty much everything is CDATA type. + */ + private static final String CDATA = "CDATA"; + + /** + * Gets the number of attributes. + */ + public abstract int getLength(); + + /** + * Gets the pointer to the parser. We need this so we can get to the + * interned string pool. + */ + abstract int getParserPointer(); + + /** + * Gets the pointer to the underlying attribute array. Can be 0 if the + * length is 0. + */ + public abstract int getPointer(); + + public String getURI(int index) { + if (index < 0 || index >= getLength()) { + return null; + } + return getURI(getParserPointer(), getPointer(), index); + } + + public String getLocalName(int index) { + return (index < 0 || index >= getLength()) + ? null + : getLocalName(getParserPointer(), getPointer(), index); + } + + public String getQName(int index) { + return (index < 0 || index >= getLength()) + ? null + : getQName(getParserPointer(), getPointer(), index); + } + + public String getType(int index) { + return (index < 0 || index >= getLength()) ? null : CDATA; + } + + public String getValue(int index) { + return (index < 0 || index >= getLength()) + ? null + : getValue(getPointer(), index); + } + + public int getIndex(String uri, String localName) { + if (uri == null) { + throw new NullPointerException("uri"); + } + if (localName == null) { + throw new NullPointerException("local name"); + } + int pointer = getPointer(); + if (pointer == 0) { + return -1; + } + return getIndex(pointer, uri, localName); + } + + public int getIndex(String qName) { + if (qName == null) { + throw new NullPointerException("uri"); + } + int pointer = getPointer(); + if (pointer == 0) { + return -1; + } + return getIndex(pointer, qName); + } + + public String getType(String uri, String localName) { + if (uri == null) { + throw new NullPointerException("uri"); + } + if (localName == null) { + throw new NullPointerException("local name"); + } + return getIndex(uri, localName) == -1 ? null : CDATA; + } + + public String getType(String qName) { + return getIndex(qName) == -1 ? null : CDATA; + } + + public String getValue(String uri, String localName) { + if (uri == null) { + throw new NullPointerException("uri"); + } + if (localName == null) { + throw new NullPointerException("local name"); + } + int pointer = getPointer(); + if (pointer == 0) { + return null; + } + return getValue(pointer, uri, localName); + } + + public String getValue(String qName) { + if (qName == null) { + throw new NullPointerException("qName"); + } + int pointer = getPointer(); + if (pointer == 0) { + return null; + } + return getValue(pointer, qName); + } + + static native String getURI(int pointer, int attributePointer, int index); + static native String getLocalName(int pointer, int attributePointer, + int index); + static native String getQName(int pointer, int attributePointer, + int index); + static native String getValue(int attributePointer, int index); + static native int getIndex(int attributePointer, String uri, + String localName); + static native int getIndex(int attributePointer, String qName); + static native String getValue(int attributePointer, + String uri, String localName); + static native String getValue(int attributePointer, String qName); + static native void freeAttributes(int pointer); +} diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatException.java b/xml/src/main/java/org/apache/harmony/xml/ExpatException.java new file mode 100644 index 0000000..da3db9d --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/ExpatException.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml; + +/** + * Used internally to propogate Expat errors. We convert these exceptions into + * SAXParseExceptions before propogating them to the client. + */ +class ExpatException extends Exception { + + public ExpatException(String message) { + super(message); + } +} diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java b/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java new file mode 100644 index 0000000..60d74b8 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java @@ -0,0 +1,794 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.ext.LexicalHandler; + +import java.io.Reader; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URLConnection; +import java.net.URL; +import java.util.logging.Logger; +import java.util.logging.Level; + +/** + * Adapts SAX API to the Expat native XML parser. Not intended for reuse + * across documents. + * + * @see org.apache.harmony.xml.ExpatPullParser + * @see org.apache.harmony.xml.ExpatReader + */ +class ExpatParser { + + private static final int BUFFER_SIZE = 8096; // in bytes + + /** Pointer to XML_Parser instance. */ + private int pointer; + + private boolean inStartElement = false; + private int attributeCount = -1; + private int attributePointer = 0; + + private final Locator locator = new ExpatLocator(); + + private final ExpatReader xmlReader; + + private final String publicId; + private final String systemId; + + private final String encoding; + + private final ExpatAttributes attributes = new CurrentAttributes(); + + private static final String OUTSIDE_START_ELEMENT + = "Attributes can only be used within the scope of startElement()."; + + /** We default to UTF-8 when the user doesn't specify an encoding. */ + private static final String DEFAULT_ENCODING = "UTF-8"; + + /** Encoding used for Java chars, used to parse Readers and Strings */ + /*package*/ static final String CHARACTER_ENCODING = "UTF-16"; + + /** Timeout for HTTP connections (in ms) */ + private static final int TIMEOUT = 20 * 1000; + + /** + * Constructs a new parser with the specified encoding. + */ + /*package*/ ExpatParser(String encoding, ExpatReader xmlReader, + boolean processNamespaces, String publicId, String systemId) { + this.publicId = publicId; + this.systemId = systemId; + + this.xmlReader = xmlReader; + + /* + * TODO: Let Expat try to guess the encoding instead of defaulting. + * Unfortunately, I don't know how to tell which encoding Expat picked, + * so I won't know how to encode "<externalEntity>" below. The solution + * I think is to fix Expat to not require the "<externalEntity>" + * workaround. + */ + this.encoding = encoding == null ? DEFAULT_ENCODING : encoding; + this.pointer = initialize( + this.encoding, + processNamespaces + ); + } + + /** + * Used by {@link EntityParser}. + */ + private ExpatParser(String encoding, ExpatReader xmlReader, int pointer, + String publicId, String systemId) { + this.encoding = encoding; + this.xmlReader = xmlReader; + this.pointer = pointer; + this.systemId = systemId; + this.publicId = publicId; + } + + /** + * Initializes native resources. + * + * @return the pointer to the native parser + */ + private native int initialize(String encoding, boolean namespacesEnabled); + + /** + * Called at the start of an element. + * + * @param uri namespace URI of element or "" if namespace processing is + * disabled + * @param localName local name of element or "" if namespace processing is + * disabled + * @param qName qualified name or "" if namespace processing is enabled + * @param attributePointer pointer to native attribute char*--we keep + * a separate pointer so we can detach it from the parser instance + * @param attributeCount number of attributes + */ + /*package*/ void startElement(String uri, String localName, String qName, + int attributePointer, int attributeCount) throws SAXException { + ContentHandler contentHandler = xmlReader.contentHandler; + if (contentHandler == null) { + return; + } + + try { + inStartElement = true; + this.attributePointer = attributePointer; + this.attributeCount = attributeCount; + + contentHandler.startElement( + uri, localName, qName, this.attributes); + } + finally { + inStartElement = false; + this.attributeCount = -1; + this.attributePointer = 0; + } + } + + /*package*/ void endElement(String uri, String localName, String qName) + throws SAXException { + ContentHandler contentHandler = xmlReader.contentHandler; + if (contentHandler != null) { + contentHandler.endElement(uri, localName, qName); + } + } + + /*package*/ void text(char[] text, int length) throws SAXException { + ContentHandler contentHandler = xmlReader.contentHandler; + if (contentHandler != null) { + contentHandler.characters(text, 0, length); + } + } + + /*package*/ void comment(char[] text, int length) throws SAXException { + LexicalHandler lexicalHandler = xmlReader.lexicalHandler; + if (lexicalHandler != null) { + lexicalHandler.comment(text, 0, length); + } + } + + /*package*/ void startCdata() throws SAXException { + LexicalHandler lexicalHandler = xmlReader.lexicalHandler; + if (lexicalHandler != null) { + lexicalHandler.startCDATA(); + } + } + + /*package*/ void endCdata() throws SAXException { + LexicalHandler lexicalHandler = xmlReader.lexicalHandler; + if (lexicalHandler != null) { + lexicalHandler.endCDATA(); + } + } + + /*package*/ void startNamespace(String prefix, String uri) + throws SAXException { + ContentHandler contentHandler = xmlReader.contentHandler; + if (contentHandler != null) { + contentHandler.startPrefixMapping(prefix, uri); + } + } + + /*package*/ void endNamespace(String prefix) throws SAXException { + ContentHandler contentHandler = xmlReader.contentHandler; + if (contentHandler != null) { + contentHandler.endPrefixMapping(prefix); + } + } + + /*package*/ void startDtd(String name, String publicId, String systemId) + throws SAXException { + LexicalHandler lexicalHandler = xmlReader.lexicalHandler; + if (lexicalHandler != null) { + lexicalHandler.startDTD(name, publicId, systemId); + } + } + + /*package*/ void endDtd() throws SAXException { + LexicalHandler lexicalHandler = xmlReader.lexicalHandler; + if (lexicalHandler != null) { + lexicalHandler.endDTD(); + } + } + + /*package*/ void processingInstruction(String target, String data) + throws SAXException { + ContentHandler contentHandler = xmlReader.contentHandler; + if (contentHandler != null) { + contentHandler.processingInstruction(target, data); + } + } + + /** + * Handles an external entity. + * + * @param context to be passed back to Expat when we parse the entity + * @param publicId the publicId of the entity + * @param systemId the systemId of the entity + */ + /*package*/ void handleExternalEntity(String context, String publicId, + String systemId) throws SAXException, IOException { + EntityResolver entityResolver = xmlReader.entityResolver; + if (entityResolver == null) { + return; + } + + /* + * The spec. is terribly under-specified here. It says that if the + * systemId is a URL, we should try to resolve it, but it doesn't + * specify how to tell whether or not the systemId is a URL let alone + * how to resolve it. + * + * Other implementations do various insane things. We try to keep it + * simple: if the systemId parses as a URI and it's relative, we try to + * resolve it against the parent document's systemId. If anything goes + * wrong, we go with the original systemId. If crazybob had designed + * the API, he would have left all resolving to the EntityResolver. + */ + if (this.systemId != null) { + try { + URI systemUri = new URI(systemId); + if (!systemUri.isAbsolute() && !systemUri.isOpaque()) { + // It could be relative (or it may not be a URI at all!) + URI baseUri = new URI(this.systemId); + systemUri = baseUri.resolve(systemUri); + + // Replace systemId w/ resolved URI + systemId = systemUri.toString(); + } + } catch (Exception e) { + Logger.getLogger(ExpatParser.class.getName()).log(Level.INFO, + "Could not resolve '" + systemId + "' relative to" + + " '" + this.systemId + "' at " + locator, e); + } + } + + InputSource inputSource = entityResolver.resolveEntity( + publicId, systemId); + if (inputSource == null) { + /* + * The spec. actually says that we should try to treat systemId + * as a URL and download and parse its contents here, but an + * entity resolver can easily accomplish the same by returning + * new InputSource(systemId). + * + * Downloading external entities by default would result in several + * unwanted DTD downloads, not to mention pose a security risk + * when parsing untrusted XML (http://tinyurl.com/56ggrk), + * so we just do nothing instead. This also enables the user to + * opt out of entity parsing when using + * {@link org.xml.sax.helpers.DefaultHandler}, something that + * wouldn't be possible otherwise. + */ + return; + } + + String encoding = pickEncoding(inputSource); + int pointer = createEntityParser(this.pointer, context, encoding); + try { + EntityParser entityParser = new EntityParser(encoding, xmlReader, + pointer, inputSource.getPublicId(), + inputSource.getSystemId()); + + parseExternalEntity(entityParser, inputSource); + } finally { + releaseParser(pointer); + } + } + + /** + * Picks an encoding for an external entity. Defaults to UTF-8. + */ + private String pickEncoding(InputSource inputSource) { + Reader reader = inputSource.getCharacterStream(); + if (reader != null) { + return CHARACTER_ENCODING; + } + + String encoding = inputSource.getEncoding(); + return encoding == null ? DEFAULT_ENCODING : encoding; + } + + /** + * Parses the the external entity provided by the input source. + */ + private void parseExternalEntity(ExpatParser entityParser, + InputSource inputSource) throws IOException, SAXException { + /* + * Expat complains if the external entity isn't wrapped with a root + * element so we add one and ignore it later on during parsing. + */ + + // Try the character stream. + Reader reader = inputSource.getCharacterStream(); + if (reader != null) { + try { + entityParser.append("<externalEntity>"); + entityParser.parseFragment(reader); + entityParser.append("</externalEntity>"); + } finally { + // TODO: Don't eat original exception when close() throws. + reader.close(); + } + return; + } + + // Try the byte stream. + InputStream in = inputSource.getByteStream(); + if (in != null) { + try { + entityParser.append("<externalEntity>" + .getBytes(entityParser.encoding)); + entityParser.parseFragment(in); + entityParser.append("</externalEntity>" + .getBytes(entityParser.encoding)); + } finally { + // TODO: Don't eat original exception when close() throws. + in.close(); + } + return; + } + + // Make sure we use the user-provided systemId. + String systemId = inputSource.getSystemId(); + if (systemId == null) { + // TODO: We could just try our systemId here. + throw new ParseException("No input specified.", locator); + } + + // Try the system id. + in = openUrl(systemId); + try { + entityParser.append("<externalEntity>" + .getBytes(entityParser.encoding)); + entityParser.parseFragment(in); + entityParser.append("</externalEntity>" + .getBytes(entityParser.encoding)); + } finally { + in.close(); + } + } + + /** + * Creates a native entity parser. + * + * @param parentPointer pointer to parent Expat parser + * @param context passed to {@link #handleExternalEntity} + * @param encoding + * @return pointer to native parser + */ + private static native int createEntityParser(int parentPointer, + String context, String encoding); + + /** + * Appends part of an XML document. This parser will parse the given XML to + * the extent possible and dispatch to the appropriate methods. + * + * @param xml a whole or partial snippet of XML + * @throws SAXException if an error occurs during parsing + */ + /*package*/ void append(String xml) throws SAXException { + try { + append(this.pointer, xml, false); + } catch (ExpatException e) { + throw new ParseException(e.getMessage(), this.locator); + } + } + + private native void append(int pointer, String xml, boolean isFinal) + throws SAXException, ExpatException; + + /** + * Appends part of an XML document. This parser will parse the given XML to + * the extent possible and dispatch to the appropriate methods. + * + * @param xml a whole or partial snippet of XML + * @param offset into the char[] + * @param length of characters to use + * @throws SAXException if an error occurs during parsing + */ + /*package*/ void append(char[] xml, int offset, int length) + throws SAXException { + try { + append(this.pointer, xml, offset, length); + } catch (ExpatException e) { + throw new ParseException(e.getMessage(), this.locator); + } + } + + private native void append(int pointer, char[] xml, int offset, + int length) throws SAXException, ExpatException; + + /** + * Appends part of an XML document. This parser will parse the given XML to + * the extent possible and dispatch to the appropriate methods. + * + * @param xml a whole or partial snippet of XML + * @throws SAXException if an error occurs during parsing + */ + /*package*/ void append(byte[] xml) throws SAXException { + append(xml, 0, xml.length); + } + + /** + * Appends part of an XML document. This parser will parse the given XML to + * the extent possible and dispatch to the appropriate methods. + * + * @param xml a whole or partial snippet of XML + * @param offset into the byte[] + * @param length of bytes to use + * @throws SAXException if an error occurs during parsing + */ + /*package*/ void append(byte[] xml, int offset, int length) + throws SAXException { + try { + append(this.pointer, xml, offset, length); + } catch (ExpatException e) { + throw new ParseException(e.getMessage(), this.locator); + } + } + + private native void append(int pointer, byte[] xml, int offset, + int length) throws SAXException, ExpatException; + + /** + * Parses an XML document from the given input stream. + */ + /*package*/ void parseDocument(InputStream in) throws IOException, + SAXException { + startDocument(); + parseFragment(in); + finish(); + endDocument(); + } + + /** + * Parses an XML Document from the given reader. + */ + /*package*/ void parseDocument(Reader in) throws IOException, SAXException { + startDocument(); + parseFragment(in); + finish(); + endDocument(); + } + + /** + * Parses XML from the given Reader. + */ + private void parseFragment(Reader in) throws IOException, SAXException { + char[] buffer = new char[BUFFER_SIZE / 2]; + int length; + while ((length = in.read(buffer)) != -1) { + try { + append(this.pointer, buffer, 0, length); + } catch (ExpatException e) { + throw new ParseException(e.getMessage(), locator); + } + } + } + + /** + * Parses XML from the given input stream. + */ + private void parseFragment(InputStream in) + throws IOException, SAXException { + byte[] buffer = new byte[BUFFER_SIZE]; + int length; + while ((length = in.read(buffer)) != -1) { + try { + append(this.pointer, buffer, 0, length); + } catch (ExpatException e) { + throw new ParseException(e.getMessage(), this.locator); + } + } + } + + private void startDocument() throws SAXException { + ContentHandler contentHandler = xmlReader.contentHandler; + if (contentHandler != null) { + contentHandler.setDocumentLocator(this.locator); + contentHandler.startDocument(); + } + } + + private void endDocument() throws SAXException { + ContentHandler contentHandler; + contentHandler = xmlReader.contentHandler; + if (contentHandler != null) { + contentHandler.endDocument(); + } + } + + /** + * Indicate that we're finished parsing. + * + * @throws SAXException if the xml is incomplete + */ + /*package*/ void finish() throws SAXException { + try { + append(this.pointer, "", true); + } catch (ExpatException e) { + throw new ParseException(e.getMessage(), this.locator); + } + } + + @Override + @SuppressWarnings("FinalizeDoesntCallSuperFinalize") + protected synchronized void finalize() throws Throwable { + if (this.pointer != 0) { + release(this.pointer); + this.pointer = 0; + } + } + + /** + * Releases all native objects. + */ + private native void release(int pointer); + + /** + * Releases native parser only. + */ + private static native void releaseParser(int pointer); + + /** + * Initialize static resources. + */ + private static native void staticInitialize(String emptyString); + + static { + staticInitialize(""); + } + + /** + * Gets the current line number within the XML file. + */ + private int line() { + return line(this.pointer); + } + + private static native int line(int pointer); + + /** + * Gets the current column number within the XML file. + */ + private int column() { + return column(this.pointer); + } + + private static native int column(int pointer); + + /** + * Clones the current attributes so they can be used outside of + * startElement(). + */ + /*package*/ Attributes cloneAttributes() { + if (!inStartElement) { + throw new IllegalStateException(OUTSIDE_START_ELEMENT); + } + + if (attributeCount == 0) { + return ClonedAttributes.EMPTY; + } + + int clonePointer + = cloneAttributes(this.attributePointer, this.attributeCount); + return new ClonedAttributes(pointer, clonePointer, attributeCount); + } + + private static native int cloneAttributes(int pointer, int attributeCount); + + /** + * Used for cloned attributes. + */ + private static class ClonedAttributes extends ExpatAttributes { + + private static final Attributes EMPTY = new ClonedAttributes(0, 0, 0); + + private final int parserPointer; + private int pointer; + private final int length; + + /** + * Constructs a Java wrapper for native attributes. + * + * @param parserPointer pointer to the parse, can be 0 if length is 0. + * @param pointer pointer to the attributes array, can be 0 if the + * length is 0. + * @param length number of attributes + */ + private ClonedAttributes(int parserPointer, int pointer, int length) { + this.parserPointer = parserPointer; + this.pointer = pointer; + this.length = length; + } + + @Override + public int getParserPointer() { + return this.parserPointer; + } + + @Override + public int getPointer() { + return pointer; + } + + @Override + public int getLength() { + return length; + } + + @Override + @SuppressWarnings("FinalizeDoesntCallSuperFinalize") + protected synchronized void finalize() throws Throwable { + if (pointer != 0) { + freeAttributes(pointer); + pointer = 0; + } + } + } + + private class ExpatLocator implements Locator { + + public String getPublicId() { + return publicId; + } + + public String getSystemId() { + return systemId; + } + + public int getLineNumber() { + return line(); + } + + public int getColumnNumber() { + return column(); + } + + @Override + public String toString() { + return "Locator[publicId: " + publicId + ", systemId: " + systemId + + ", line: " + getLineNumber() + + ", column: " + getColumnNumber() + "]"; + } + } + + /** + * Attributes that are only valid during startElement(). + */ + private class CurrentAttributes extends ExpatAttributes { + + @Override + public int getParserPointer() { + return pointer; + } + + @Override + public int getPointer() { + if (!inStartElement) { + throw new IllegalStateException(OUTSIDE_START_ELEMENT); + } + return attributePointer; + } + + @Override + public int getLength() { + if (!inStartElement) { + throw new IllegalStateException(OUTSIDE_START_ELEMENT); + } + return attributeCount; + } + } + + /** + * Includes line and column in the message. + */ + private static class ParseException extends SAXParseException { + + private ParseException(String message, Locator locator) { + super(makeMessage(message, locator), locator); + } + + private static String makeMessage(String message, Locator locator) { + return makeMessage(message, locator.getLineNumber(), + locator.getColumnNumber()); + } + + private static String makeMessage( + String message, int line, int column) { + return "At line " + line + ", column " + + column + ": " + message; + } + } + + /** + * Opens an InputStream for the given URL. + */ + /*package*/ static InputStream openUrl(String url) throws IOException { + try { + URLConnection urlConnection = new URL(url).openConnection(); + urlConnection.setConnectTimeout(TIMEOUT); + urlConnection.setReadTimeout(TIMEOUT); + urlConnection.setDoInput(true); + urlConnection.setDoOutput(false); + return urlConnection.getInputStream(); + } catch (Exception e) { + IOException ioe = new IOException("Couldn't open " + url); + ioe.initCause(e); + throw ioe; + } + } + + /** + * Parses an external entity. + */ + private static class EntityParser extends ExpatParser { + + private int depth = 0; + + private EntityParser(String encoding, ExpatReader xmlReader, + int pointer, String publicId, String systemId) { + super(encoding, xmlReader, pointer, publicId, systemId); + } + + @Override + void startElement(String uri, String localName, String qName, + int attributePointer, int attributeCount) throws SAXException { + /* + * Skip topmost element generated by our workaround in + * {@link #handleExternalEntity}. + */ + if (depth++ > 0) { + super.startElement(uri, localName, qName, attributePointer, + attributeCount); + } + } + + @Override + void endElement(String uri, String localName, String qName) + throws SAXException { + if (--depth > 0) { + super.endElement(uri, localName, qName); + } + } + + @Override + @SuppressWarnings("FinalizeDoesntCallSuperFinalize") + protected synchronized void finalize() throws Throwable { + /* + * Don't release our native resources. We do so explicitly in + * {@link #handleExternalEntity} and we don't want to release the + * parsing context--our parent is using it. + */ + } + } +} + diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatPullParser.java b/xml/src/main/java/org/apache/harmony/xml/ExpatPullParser.java new file mode 100644 index 0000000..4759718 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/ExpatPullParser.java @@ -0,0 +1,964 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +/** + * Fast, partial XmlPullParser implementation based upon Expat. Does not + * support validation or {@code DOCTYPE} processing. + */ +public class ExpatPullParser implements XmlPullParser { + /** + * This feature is identified by http://xmlpull.org/v1/doc/features.html#relaxed + * If this feature is supported that means that XmlPull parser will be + * lenient when checking XML well formedness. + * NOTE: use it only if XML input is not well-formed and in general usage + * if this feature is discouraged + * NOTE: as there is no definition of what is relaxed XML parsing + * therefore what parser will do completely depends on implementation used + */ + public static final String FEATURE_RELAXED = + "http://xmlpull.org/v1/doc/features.html#relaxed"; + + private static final int BUFFER_SIZE = 8096; + + private static final String NOT_A_START_TAG = "This is not a start tag."; + + private Document document; + private boolean processNamespaces = false; + private boolean relaxed = false; + + public void setFeature(String name, boolean state) + throws XmlPullParserException { + if (name == null) { + // Required by API. + throw new IllegalArgumentException("Null feature name"); + } + + if (name.equals(FEATURE_PROCESS_NAMESPACES)) { + processNamespaces = state; + return; + } + + if (name.equals(FEATURE_RELAXED)) { + relaxed = true; + return; + } + + // You're free to turn these features off because we don't support them. + if (!state && (name.equals(FEATURE_REPORT_NAMESPACE_ATTRIBUTES) + || name.equals(FEATURE_PROCESS_DOCDECL) + || name.equals(FEATURE_VALIDATION))) { + return; + } + + throw new XmlPullParserException("Unsupported feature: " + name); + } + + public boolean getFeature(String name) { + if (name == null) { + // Required by API. + throw new IllegalArgumentException("Null feature name"); + } + + // We always support namespaces, but no other features. + return name.equals(FEATURE_PROCESS_NAMESPACES) && processNamespaces; + } + + /** + * Returns true if this parser processes namespaces. + * + * @see #setNamespaceProcessingEnabled(boolean) + */ + public boolean isNamespaceProcessingEnabled() { + return processNamespaces; + } + + /** + * Enables or disables namespace processing. Set to false by default. + * + * @see #isNamespaceProcessingEnabled() + */ + public void setNamespaceProcessingEnabled(boolean processNamespaces) { + this.processNamespaces = processNamespaces; + } + + public void setProperty(String name, Object value) + throws XmlPullParserException { + if (name == null) { + // Required by API. + throw new IllegalArgumentException("Null feature name"); + } + + // We don't support any properties. + throw new XmlPullParserException("Properties aren't supported."); + } + + public Object getProperty(String name) { + return null; + } + + public void setInput(Reader in) throws XmlPullParserException { + this.document = new CharDocument(in, processNamespaces); + } + + public void setInput(InputStream in, String encodingName) + throws XmlPullParserException { + this.document = new ByteDocument(in, encodingName, processNamespaces); + } + + public String getInputEncoding() { + return this.document.getEncoding(); + } + + /** + * Not supported. + * + * @throws UnsupportedOperationException always + */ + public void defineEntityReplacementText(String entityName, + String replacementText) throws XmlPullParserException { + throw new UnsupportedOperationException(); + } + + public int getNamespaceCount(int depth) throws XmlPullParserException { + return document.currentEvent.namespaceStack.countAt(depth); + } + + public String getNamespacePrefix(int pos) throws XmlPullParserException { + String prefix = document.currentEvent.namespaceStack.prefixAt(pos); + @SuppressWarnings("StringEquality") + boolean hasPrefix = prefix != ""; + return hasPrefix ? prefix : null; + } + + public String getNamespaceUri(int pos) throws XmlPullParserException { + return document.currentEvent.namespaceStack.uriAt(pos); + } + + public String getNamespace(String prefix) { + // In XmlPullParser API, null == default namespace. + if (prefix == null) { + // Internally, we use empty string instead of null. + prefix = ""; + } + + return document.currentEvent.namespaceStack.uriFor(prefix); + } + + public int getDepth() { + return this.document.getDepth(); + } + + public String getPositionDescription() { + return "line " + getLineNumber() + ", column " + getColumnNumber(); + } + + /** + * Not supported. + * + * @return {@literal -1} always + */ + public int getLineNumber() { + // We would have to record the line number in each event. + return -1; + } + + /** + * Not supported. + * + * @return {@literal -1} always + */ + public int getColumnNumber() { + // We would have to record the column number in each event. + return -1; + } + + public boolean isWhitespace() throws XmlPullParserException { + if (getEventType() != TEXT) { + throw new XmlPullParserException("Not on text."); + } + + String text = getText(); + + if (text.length() == 0) { + return true; + } + + int length = text.length(); + for (int i = 0; i < length; i++) { + if (!Character.isWhitespace(text.charAt(i))) { + return false; + } + } + + return true; + } + + public String getText() { + final StringBuilder builder = this.document.currentEvent.getText(); + return builder == null ? null : builder.toString(); + } + + public char[] getTextCharacters(int[] holderForStartAndLength) { + final StringBuilder builder = this.document.currentEvent.getText(); + + final int length = builder.length(); + char[] characters = new char[length]; + builder.getChars(0, length, characters, 0); + + holderForStartAndLength[0] = 0; + holderForStartAndLength[1] = length; + + return characters; + } + + public String getNamespace() { + return this.document.currentEvent.getNamespace(); + } + + public String getName() { + return this.document.currentEvent.getName(); + } + + /** + * Not supported. + * + * @throws UnsupportedOperationException always + */ + public String getPrefix() { + throw new UnsupportedOperationException(); + } + + public boolean isEmptyElementTag() throws XmlPullParserException { + return this.document.isCurrentElementEmpty(); + } + + public int getAttributeCount() { + return this.document.currentEvent.getAttributeCount(); + } + + public String getAttributeNamespace(int index) { + return this.document.currentEvent.getAttributeNamespace(index); + } + + public String getAttributeName(int index) { + return this.document.currentEvent.getAttributeName(index); + } + + /** + * Not supported. + * + * @throws UnsupportedOperationException always + */ + public String getAttributePrefix(int index) { + throw new UnsupportedOperationException(); + } + + public String getAttributeType(int index) { + return "CDATA"; + } + + public boolean isAttributeDefault(int index) { + return false; + } + + public String getAttributeValue(int index) { + return this.document.currentEvent.getAttributeValue(index); + } + + public String getAttributeValue(String namespace, String name) { + return this.document.currentEvent.getAttributeValue(namespace, name); + } + + public int getEventType() throws XmlPullParserException { + return this.document.currentEvent.getType(); + } + + public int next() throws XmlPullParserException, IOException { + return this.document.dequeue(); + } + + /** + * Not supported. + * + * @throws UnsupportedOperationException always + */ + public int nextToken() throws XmlPullParserException, IOException { + throw new UnsupportedOperationException(); + } + + public void require(int type, String namespace, String name) + throws XmlPullParserException, IOException { + if (type != getEventType() + || (namespace != null && !namespace.equals(getNamespace())) + || (name != null && !name.equals(getName()))) { + throw new XmlPullParserException("expected " + + TYPES[type] + getPositionDescription()); + } + } + + public String nextText() throws XmlPullParserException, IOException { + if (this.document.currentEvent.getType() != START_TAG) + throw new XmlPullParserException("Not on start tag."); + + int next = this.document.dequeue(); + switch (next) { + case TEXT: return getText(); + case END_TAG: return ""; + default: throw new XmlPullParserException( + "Unexpected event type: " + TYPES[next]); + } + } + + public int nextTag() throws XmlPullParserException, IOException { + int eventType = next(); + if (eventType == TEXT && isWhitespace()) { + eventType = next(); + } + if (eventType != START_TAG && eventType != END_TAG) { + throw new XmlPullParserException( + "Expected start or end tag", this, null); + } + return eventType; + } + + /** + * Immutable namespace stack. Pushing a new namespace on to the stack + * only results in one object allocation. Most operations are O(N) where + * N is the stack size. Accessing recently pushed namespaces, like those + * for the current element, is significantly faster. + */ + static class NamespaceStack { + + /** An empty stack. */ + static final NamespaceStack EMPTY = new NamespaceStack(); + + private final NamespaceStack parent; + private final String prefix; + private final String uri; + private final int index; + private final int depth; + + /** + * Constructs an actual namespace stack node. Internally, the nodes + * and the stack are one in the same making for a very efficient + * implementation. The user just sees an immutable stack and the + * builder. + */ + private NamespaceStack(NamespaceStack parent, String prefix, + String uri, int depth) { + this.parent = parent; + this.prefix = prefix; + this.uri = uri; + this.index = parent.index + 1; + this.depth = depth; + } + + /** + * Constructs a dummy node which only serves to point to the bottom + * of the stack. Using an actual node instead of null simplifies the + * code. + */ + private NamespaceStack() { + this.parent = null; + this.prefix = null; + this.uri = null; + + // This node has an index of -1 since the actual first node in the + // stack has index 0. + this.index = -1; + + // The actual first node will have a depth of 1. + this.depth = 0; + } + + String uriFor(String prefix) { + for (NamespaceStack node = this; node.index >= 0; + node = node.parent) { + if (node.prefix.equals(prefix)) { + return node.uri; + } + } + + // Not found. + return null; + } + + /** + * Gets the prefix at the given index in the stack. + */ + String prefixAt(int index) { + return nodeAt(index).prefix; + } + + /** + * Gets the URI at the given index in the stack. + */ + String uriAt(int index) { + return nodeAt(index).uri; + } + + private NamespaceStack nodeAt(int index) { + if (index > this.index) { + throw new IndexOutOfBoundsException("Index > size."); + } + if (index < 0) { + throw new IndexOutOfBoundsException("Index < 0."); + } + + NamespaceStack node = this; + while (index != node.index) { + node = node.parent; + } + return node; + } + + /** + * Gets the size of the stack at the given element depth. + */ + int countAt(int depth) { + if (depth > this.depth) { + throw new IndexOutOfBoundsException("Depth > maximum."); + } + if (depth < 0) { + throw new IndexOutOfBoundsException("Depth < 0."); + } + + NamespaceStack node = this; + while (depth < node.depth) { + node = node.parent; + } + return node.index + 1; + } + + /** Builds a NamespaceStack. */ + static class Builder { + + NamespaceStack top = EMPTY; + + /** + * Pushes a namespace onto the stack. + * + * @param depth of the element upon which the namespace was + * declared + */ + void push(String prefix, String uri, int depth) { + top = new NamespaceStack(top, prefix, uri, depth); + } + + /** + * Pops all namespaces from the given element depth. + */ + void pop(int depth) { + // Remove all nodes at the specified depth. + while (top != null && top.depth == depth) { + top = top.parent; + } + } + + /** Returns the current stack. */ + NamespaceStack build() { + return top; + } + } + } + + /** + * Base class for events. Implements event chaining and defines event API + * along with common implementations which can be overridden. + */ + static abstract class Event { + + /** Element depth at the time of this event. */ + final int depth; + + /** The namespace stack at the time of this event. */ + final NamespaceStack namespaceStack; + + /** Next event in the queue. */ + Event next = null; + + Event(int depth, NamespaceStack namespaceStack) { + this.depth = depth; + this.namespaceStack = namespaceStack; + } + + void setNext(Event next) { + this.next = next; + } + + Event getNext() { + return next; + } + + StringBuilder getText() { + return null; + } + + String getNamespace() { + return null; + } + + String getName() { + return null; + } + + int getAttributeCount() { + return -1; + } + + String getAttributeNamespace(int index) { + throw new IndexOutOfBoundsException(NOT_A_START_TAG); + } + + String getAttributeName(int index) { + throw new IndexOutOfBoundsException(NOT_A_START_TAG); + } + + String getAttributeValue(int index) { + throw new IndexOutOfBoundsException(NOT_A_START_TAG); + } + + abstract int getType(); + + String getAttributeValue(String namespace, String name) { + throw new IndexOutOfBoundsException(NOT_A_START_TAG); + } + + public int getDepth() { + return this.depth; + } + } + + static class StartDocumentEvent extends Event { + + public StartDocumentEvent() { + super(0, NamespaceStack.EMPTY); + } + + @Override + int getType() { + return START_DOCUMENT; + } + } + + static class StartTagEvent extends Event { + + final String name; + final String namespace; + final Attributes attributes; + final boolean processNamespaces; + + StartTagEvent(String namespace, + String name, + ExpatParser expatParser, + int depth, + NamespaceStack namespaceStack, + boolean processNamespaces) { + super(depth, namespaceStack); + this.namespace = namespace; + this.name = name; + this.attributes = expatParser.cloneAttributes(); + this.processNamespaces = processNamespaces; + } + + @Override + String getNamespace() { + return namespace; + } + + @Override + String getName() { + return name; + } + + @Override + int getAttributeCount() { + return attributes.getLength(); + } + + @Override + String getAttributeNamespace(int index) { + return attributes.getURI(index); + } + + @Override + String getAttributeName(int index) { + return processNamespaces ? attributes.getLocalName(index) + : attributes.getQName(index); + } + + @Override + String getAttributeValue(int index) { + return attributes.getValue(index); + } + + @Override + String getAttributeValue(String namespace, String name) { + if (namespace == null) { + namespace = ""; + } + + return attributes.getValue(namespace, name); + } + + @Override + int getType() { + return START_TAG; + } + } + + static class EndTagEvent extends Event { + + final String namespace; + final String localName; + + EndTagEvent(String namespace, String localName, int depth, + NamespaceStack namespaceStack) { + super(depth, namespaceStack); + this.namespace = namespace; + this.localName = localName; + } + + @Override + String getName() { + return this.localName; + } + + @Override + String getNamespace() { + return this.namespace; + } + + @Override + int getType() { + return END_TAG; + } + } + + static class TextEvent extends Event { + + final StringBuilder builder; + + public TextEvent(int initialCapacity, int depth, + NamespaceStack namespaceStack) { + super(depth, namespaceStack); + this.builder = new StringBuilder(initialCapacity); + } + + @Override + int getType() { + return TEXT; + } + + @Override + StringBuilder getText() { + return this.builder; + } + + void append(char[] text, int start, int length) { + builder.append(text, start, length); + } + } + + static class EndDocumentEvent extends Event { + + EndDocumentEvent() { + super(0, NamespaceStack.EMPTY); + } + + @Override + Event getNext() { + throw new IllegalStateException("End of document."); + } + + @Override + void setNext(Event next) { + throw new IllegalStateException("End of document."); + } + + @Override + int getType() { + return END_DOCUMENT; + } + } + + /** + * Encapsulates the parsing context of the current document. + */ + abstract class Document { + + final String encoding; + final ExpatParser parser; + final boolean processNamespaces; + + TextEvent textEvent = null; + boolean finished = false; + + Document(String encoding, boolean processNamespaces) { + this.encoding = encoding; + this.processNamespaces = processNamespaces; + + ExpatReader xmlReader = new ExpatReader(); + xmlReader.setContentHandler(new SaxHandler()); + + this.parser = new ExpatParser( + encoding, xmlReader, processNamespaces, null, null); + } + + /** Namespace stack builder. */ + NamespaceStack.Builder namespaceStackBuilder + = new NamespaceStack.Builder(); + + Event currentEvent = new StartDocumentEvent(); + Event last = currentEvent; + + /** + * Sends some more XML to the parser. + */ + void pump() throws IOException, XmlPullParserException { + if (this.finished) { + return; + } + + int length = buffer(); + + // End of document. + if (length == -1) { + this.finished = true; + if (!relaxed) { + try { + parser.finish(); + } catch (SAXException e) { + throw new XmlPullParserException( + "Premature end of document.", ExpatPullParser.this, e); + } + } + add(new EndDocumentEvent()); + return; + } + + if (length == 0) { + return; + } + + flush(parser, length); + } + + /** + * Reads data into the buffer. + * + * @return the length of data buffered or {@code -1} if we've reached + * the end of the data. + */ + abstract int buffer() throws IOException; + + /** + * Sends buffered data to the parser. + * + * @param parser the parser to flush to + * @param length of data buffered + */ + abstract void flush(ExpatParser parser, int length) + throws XmlPullParserException; + + /** + * Adds an event. + */ + void add(Event event) { + // Flush pre-exising text event if necessary. + if (textEvent != null) { + last.setNext(textEvent); + last = textEvent; + textEvent = null; + } + + last.setNext(event); + last = event; + } + + /** + * Moves to the next event in the queue. + * + * @return type of next event + */ + int dequeue() throws XmlPullParserException, IOException { + Event next; + + while ((next = currentEvent.getNext()) == null) { + pump(); + } + + currentEvent.next = null; + currentEvent = next; + + return currentEvent.getType(); + } + + String getEncoding() { + return this.encoding; + } + + int getDepth() { + return currentEvent.getDepth(); + } + + /** + * Returns true if we're on a start element and the next event is + * its corresponding end element. + * + * @throws XmlPullParserException if we aren't on a start element + */ + boolean isCurrentElementEmpty() throws XmlPullParserException { + if (currentEvent.getType() != START_TAG) { + throw new XmlPullParserException(NOT_A_START_TAG); + } + + Event next; + + try { + while ((next = currentEvent.getNext()) == null) { + pump(); + } + } catch (IOException ex) { + throw new XmlPullParserException(ex.toString()); + } + + return next.getType() == END_TAG; + } + + private class SaxHandler implements ContentHandler { + + int depth = 0; + + public void startPrefixMapping(String prefix, String uri) + throws SAXException { + // Depth + 1--we aren't actually in the element yet. + namespaceStackBuilder.push(prefix, uri, depth + 1); + } + + public void startElement(String uri, String localName, String qName, + Attributes attributes) { + String name = processNamespaces ? localName : qName; + + add(new StartTagEvent(uri, name, parser, ++this.depth, + namespaceStackBuilder.build(), processNamespaces)); + } + + public void endElement(String uri, String localName, String qName) { + String name = processNamespaces ? localName : qName; + + int depth = this.depth--; + add(new EndTagEvent(uri, name, depth, + namespaceStackBuilder.build())); + namespaceStackBuilder.pop(depth); + } + + public void characters(char ch[], int start, int length) { + // Ignore empty strings. + if (length == 0) { + return; + } + + // Start a new text event if necessary. + if (textEvent == null) { + textEvent = new TextEvent(length, this.depth, + namespaceStackBuilder.build()); + } + + // Append to an existing text event. + textEvent.append(ch, start, length); + } + + public void setDocumentLocator(Locator locator) {} + public void startDocument() throws SAXException {} + public void endDocument() throws SAXException {} + public void endPrefixMapping(String prefix) throws SAXException {} + public void ignorableWhitespace(char ch[], int start, int length) + throws SAXException {} + public void processingInstruction(String target, String data) + throws SAXException {} + public void skippedEntity(String name) throws SAXException {} + } + } + + class CharDocument extends Document { + + final char[] buffer = new char[BUFFER_SIZE / 2]; + final Reader in; + + CharDocument(Reader in, boolean processNamespaces) { + super("UTF-16", processNamespaces); + this.in = in; + } + + @Override + int buffer() throws IOException { + return in.read(buffer); + } + + @Override + void flush(ExpatParser parser, int length) + throws XmlPullParserException { + try { + parser.append(buffer, 0, length); + } catch (SAXException e) { + throw new XmlPullParserException( + "Error parsing document.", ExpatPullParser.this, e); + } + } + } + + class ByteDocument extends Document { + + final byte[] buffer = new byte[BUFFER_SIZE]; + final InputStream in; + + ByteDocument(InputStream in, String encoding, + boolean processNamespaces) { + super(encoding, processNamespaces); + this.in = in; + } + + @Override + int buffer() throws IOException { + return in.read(buffer); + } + + @Override + void flush(ExpatParser parser, int length) + throws XmlPullParserException { + try { + parser.append(buffer, 0, length); + } catch (SAXException e) { + throw new XmlPullParserException( + "Error parsing document.", ExpatPullParser.this, e); + } + } + } +} diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java b/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java new file mode 100644 index 0000000..a6a83a0 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml; + +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; +import org.xml.sax.ext.LexicalHandler; + +import java.io.IOException; +import java.io.Reader; +import java.io.InputStream; +import java.util.logging.Logger; + +/** + * SAX wrapper around Expat. Interns strings. Does not support validation. + * Does not support {@link DTDHandler}. + */ +public class ExpatReader implements XMLReader { + + private static final Logger logger + = Logger.getLogger(ExpatReader.class.getName()); + + /* + * ExpatParser accesses these fields directly during parsing. The user + * should be able to safely change them during parsing. + */ + /*package*/ ContentHandler contentHandler; + /*package*/ EntityResolver entityResolver; + /*package*/ ErrorHandler errorHandler; + /*package*/ LexicalHandler lexicalHandler; + + private boolean processNamespaces = true; + private boolean processNamespacePrefixes = false; + + private static final String LEXICAL_HANDLER_PROPERTY + = "http://xml.org/sax/properties/lexical-handler"; + + private static class Feature { + + private static final String BASE_URI = "http://xml.org/sax/features/"; + + private static final String VALIDATION = BASE_URI + "validation"; + private static final String NAMESPACES = BASE_URI + "namespaces"; + private static final String NAMESPACE_PREFIXES + = BASE_URI + "namespace-prefixes"; + private static final String STRING_INTERNING + = BASE_URI + "string-interning"; + } + + public boolean getFeature(String name) + throws SAXNotRecognizedException, SAXNotSupportedException { + if (name == null) { + throw new NullPointerException("name"); + } + + if (name.equals(Feature.VALIDATION)) { + return false; + } + + if (name.equals(Feature.NAMESPACES)) { + return processNamespaces; + } + + if (name.equals(Feature.NAMESPACE_PREFIXES)) { + return processNamespacePrefixes; + } + + if (name.equals(Feature.STRING_INTERNING)) { + return true; + } + + throw new SAXNotRecognizedException(name); + } + + public void setFeature(String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException { + if (name == null) { + throw new NullPointerException("name"); + } + + if (name.equals(Feature.VALIDATION)) { + if (value) { + throw new SAXNotSupportedException("Cannot enable " + name); + } else { + // Default. + return; + } + } + + if (name.equals(Feature.NAMESPACES)) { + processNamespaces = value; + return; + } + + if (name.equals(Feature.NAMESPACE_PREFIXES)) { + processNamespacePrefixes = value; + return; + } + + if (name.equals(Feature.STRING_INTERNING)) { + if (value) { + // Default. + return; + } else { + throw new SAXNotSupportedException("Cannot disable " + name); + } + } + + throw new SAXNotRecognizedException(name); + } + + public Object getProperty(String name) + throws SAXNotRecognizedException, SAXNotSupportedException { + if (name == null) { + throw new NullPointerException("name"); + } + + if (name.equals(LEXICAL_HANDLER_PROPERTY)) { + return lexicalHandler; + } + + throw new SAXNotRecognizedException(name); + } + + public void setProperty(String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException { + if (name == null) { + throw new NullPointerException("name"); + } + + if (name.equals(LEXICAL_HANDLER_PROPERTY)) { + // The object must implement LexicalHandler + if (value instanceof LexicalHandler) { + this.lexicalHandler = (LexicalHandler) value; + return; + } + throw new SAXNotSupportedException("value doesn't implement " + + "org.xml.sax.ext.LexicalHandler"); + } + + throw new SAXNotRecognizedException(name); + } + + public void setEntityResolver(EntityResolver resolver) { + this.entityResolver = resolver; + } + + public EntityResolver getEntityResolver() { + return entityResolver; + } + + /** + * Not implemented. + */ + public void setDTDHandler(DTDHandler ignored) { + logger.warning("DTD handlers aren't supported."); + } + + /** + * Always returns null. + */ + public DTDHandler getDTDHandler() { + return null; + } + + public void setContentHandler(ContentHandler handler) { + this.contentHandler = handler; + } + + public ContentHandler getContentHandler() { + return this.contentHandler; + } + + public void setErrorHandler(ErrorHandler handler) { + this.errorHandler = handler; + } + + public ErrorHandler getErrorHandler() { + return errorHandler; + } + + /** + * Returns the current lexical handler. + * + * @return the current lexical handler, or null if none has been registered + * @see #setLexicalHandler + */ + public LexicalHandler getLexicalHandler() { + return lexicalHandler; + } + + /** + * Registers a lexical event handler. Supports neither + * {@link LexicalHandler#startEntity(String)} nor + * {@link LexicalHandler#endEntity(String)}. + * + * <p>If the application does not register a lexical handler, all + * lexical events reported by the SAX parser will be silently + * ignored.</p> + * + * <p>Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.</p> + * + * @param lexicalHandler listens for lexical events + * @see #getLexicalHandler() + */ + public void setLexicalHandler(LexicalHandler lexicalHandler) { + this.lexicalHandler = lexicalHandler; + } + + /** + * Returns true if this SAX parser processes namespaces. + * + * @see #setNamespaceProcessingEnabled(boolean) + */ + public boolean isNamespaceProcessingEnabled() { + return processNamespaces; + } + + /** + * Enables or disables namespace processing. Set to true by default. If you + * enable namespace processing, the parser will invoke + * {@link ContentHandler#startPrefixMapping(String, String)} and + * {@link ContentHandler#endPrefixMapping(String)}, and it will filter + * out namespace declarations from element attributes. + * + * @see #isNamespaceProcessingEnabled() + */ + public void setNamespaceProcessingEnabled(boolean processNamespaces) { + this.processNamespaces = processNamespaces; + } + + public void parse(InputSource input) throws IOException, SAXException { + if (processNamespacePrefixes == processNamespaces) { + /* + * Expat has XML_SetReturnNSTriplet, but that still doesn't + * include xmlns attributes like this feature requires. We may + * have to implement namespace processing ourselves if we want + * this (not too difficult). We obviously "support" namespace + * prefixes if namespaces are disabled. + */ + throw new SAXNotSupportedException("The 'namespace-prefix' " + + "feature is not supported while the 'namespaces' " + + "feature is enabled."); + } + + // Try the character stream. + Reader reader = input.getCharacterStream(); + if (reader != null) { + try { + parse(reader, input.getPublicId(), input.getSystemId()); + } finally { + // TODO: Don't eat original exception when close() throws. + reader.close(); + } + return; + } + + // Try the byte stream. + InputStream in = input.getByteStream(); + String encoding = input.getEncoding(); + if (in != null) { + try { + parse(in, encoding, input.getPublicId(), input.getSystemId()); + } finally { + // TODO: Don't eat original exception when close() throws. + in.close(); + } + return; + } + + String systemId = input.getSystemId(); + if (systemId == null) { + throw new SAXException("No input specified."); + } + + // Try the system id. + in = ExpatParser.openUrl(systemId); + try { + parse(in, encoding, input.getPublicId(), systemId); + } finally { + in.close(); + } + } + + private void parse(Reader in, String publicId, String systemId) + throws IOException, SAXException { + ExpatParser parser = new ExpatParser( + ExpatParser.CHARACTER_ENCODING, + this, + processNamespaces, + publicId, + systemId + ); + parser.parseDocument(in); + } + + private void parse(InputStream in, String encoding, String publicId, + String systemId) throws IOException, SAXException { + ExpatParser parser = new ExpatParser( + encoding, + this, + processNamespaces, + publicId, + systemId + ); + parser.parseDocument(in); + } + + public void parse(String systemId) throws IOException, SAXException { + parse(new InputSource(systemId)); + } +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java new file mode 100644 index 0000000..a39e0c4 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class AttrImpl extends NodeImpl implements Attr { + + // Maintained by ElementImpl. + ElementImpl ownerElement; + + private boolean namespaceAware; + + private String namespaceURI; + + private String localName; + + private String prefix; + + private String value; + + AttrImpl(DocumentImpl document, String namespaceURI, String qualifiedName) { + super(document); + + namespaceAware = true; + this.namespaceURI = namespaceURI; + + if (qualifiedName == null || "".equals(qualifiedName)) { + throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName); + } + + int prefixSeparator = qualifiedName.lastIndexOf(":"); + if (prefixSeparator != -1) { + setPrefix(qualifiedName.substring(0, prefixSeparator)); + qualifiedName = qualifiedName.substring(prefixSeparator + 1); + } + + localName = qualifiedName; + + if ("".equals(localName)) { + throw new DOMException(DOMException.NAMESPACE_ERR, localName); + } + + if ("xmlns".equals(localName) && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) { + throw new DOMException(DOMException.NAMESPACE_ERR, localName); + } + + if (!document.isXMLIdentifier(localName)) { + throw new DOMException(DOMException.INVALID_CHARACTER_ERR, localName); + } + + value = ""; + } + + AttrImpl(DocumentImpl document, String name) { + super(document); + + this.namespaceAware = false; + + int prefixSeparator = name.lastIndexOf(":"); + if (prefixSeparator != -1) { + String prefix = name.substring(0, prefixSeparator); + String localName = name.substring(prefixSeparator + 1); + + if (!document.isXMLIdentifier(prefix) || !document.isXMLIdentifier(localName)) { + throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); + } + } else { + if (!document.isXMLIdentifier(name)) { + throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); + } + } + + this.localName = name; + } + + @Override + public String getLocalName() { + return namespaceAware ? localName : null; + } + + public String getName() { + return (prefix != null ? prefix + ":" : "") + localName; + } + + @Override + public String getNamespaceURI() { + return namespaceURI; + } + + @Override + public String getNodeName() { + return getName(); + } + + public short getNodeType() { + return Node.ATTRIBUTE_NODE; + } + + @Override + public String getNodeValue() { + return getValue(); + } + + public Element getOwnerElement() { + return ownerElement; + } + + @Override + public String getPrefix() { + return prefix; + } + + public boolean getSpecified() { + return value != null; + } + + public String getValue() { + return value; + } + + @Override + public void setNodeValue(String value) throws DOMException { + setValue(value); + } + + @Override + public void setPrefix(String prefix) { + if (!namespaceAware) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + + if (prefix != null) { + if (namespaceURI == null || !document.isXMLIdentifier(prefix) || "xmlns".equals(prefix)) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + + if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + } + + this.prefix = prefix; + } + + public void setValue(String value) throws DOMException { + this.value = value; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java new file mode 100644 index 0000000..f54e5f4 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.CDATASection; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class CDATASectionImpl extends TextImpl implements CDATASection { + + CDATASectionImpl(DocumentImpl document, String data) { + super(document, data); + } + + @Override + public String getNodeName() { + return "#cdata-section"; + } + + @Override + public short getNodeType() { + return Node.CDATA_SECTION_NODE; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java new file mode 100644 index 0000000..010cb22 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.CharacterData; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public abstract class CharacterDataImpl extends LeafNodeImpl implements + CharacterData { + + private StringBuffer buffer; + + CharacterDataImpl(DocumentImpl document, String data) { + super(document); + setData(data); + } + + public void appendData(String arg) throws DOMException { + buffer.append(arg); + } + + public void deleteData(int offset, int count) throws DOMException { + buffer.delete(offset, offset + count); + } + + public String getData() throws DOMException { + return buffer.toString(); + } + + public int getLength() { + return buffer.length(); + } + + @Override + public String getNodeValue() { + return getData(); + } + + public void insertData(int offset, String arg) throws DOMException { + try { + buffer.insert(offset, arg); + } catch (ArrayIndexOutOfBoundsException ex) { + throw new DOMException(DOMException.INDEX_SIZE_ERR, null); + } + } + + public void replaceData(int offset, int count, String arg) + throws DOMException { + try { + buffer.replace(offset, offset + count, arg); + } catch (ArrayIndexOutOfBoundsException ex) { + throw new DOMException(DOMException.INDEX_SIZE_ERR, null); + } + } + + public void setData(String data) throws DOMException { + buffer = new StringBuffer(data); + } + + public String substringData(int offset, int count) throws DOMException { + try { + return buffer.substring(offset, offset + count); + } catch (ArrayIndexOutOfBoundsException ex) { + throw new DOMException(DOMException.INDEX_SIZE_ERR, null); + } + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/CommentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/CommentImpl.java new file mode 100644 index 0000000..6c1f446 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/CommentImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class CommentImpl extends CharacterDataImpl implements Comment { + + CommentImpl(DocumentImpl document, String data) { + super(document, data); + } + + @Override + public String getNodeName() { + return "#comment"; + } + + @Override + public short getNodeType() { + return Node.COMMENT_NODE; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java new file mode 100644 index 0000000..4e13d19 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.DOMException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class DOMImplementationImpl implements DOMImplementation { + + // Singleton instance. + private static DOMImplementationImpl instance; + + DOMImplementationImpl() { + } + + public Document createDocument(String namespaceURI, String qualifiedName, + DocumentType doctype) throws DOMException { + return new DocumentImpl(this, namespaceURI, qualifiedName, doctype); + } + + public DocumentType createDocumentType(String qualifiedName, + String publicId, String systemId) throws DOMException { + return new DocumentTypeImpl(this, qualifiedName, publicId, systemId); + } + + public boolean hasFeature(String feature, String version) { + // We claim to support DOM Core Level 1 & 2, nothing else. + + if ("Core".equalsIgnoreCase(feature) || "XML".equalsIgnoreCase(feature)) { + if (version == null || "".equals(version) || "1.0".equals(version) || "2.0".equals(version)) { + return true; + } + } + + return false; + } + + /** + * Requests the singleton instance of the class. Creates it first, if + * necessary. + * + * @return The singleton Android DOMImplementationImpl instance. + */ + public static DOMImplementationImpl getInstance() { + if (instance == null) { + instance = new DOMImplementationImpl(); + } + + return instance; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentFragmentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentFragmentImpl.java new file mode 100644 index 0000000..88e6175 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentFragmentImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Node; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class DocumentFragmentImpl extends InnerNodeImpl implements + DocumentFragment { + + DocumentFragmentImpl(DocumentImpl document) { + super(document); + } + + @Override + public String getNodeName() { + return "#document-fragment"; + } + + @Override + public short getNodeType() { + return Node.DOCUMENT_FRAGMENT_NODE; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java new file mode 100644 index 0000000..fbb1cac --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Attr; +import org.w3c.dom.CDATASection; +import org.w3c.dom.CharacterData; +import org.w3c.dom.Comment; +import org.w3c.dom.DOMException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.EntityReference; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class DocumentImpl extends InnerNodeImpl implements Document { + + private DOMImplementation domImplementation; + + DocumentImpl(DOMImplementationImpl impl, String namespaceURI, + String qualifiedName, DocumentType doctype) { + super(null); + + this.domImplementation = impl; + // this.document = this; + + if (doctype != null) { + appendChild(doctype); + } + + if (qualifiedName != null) { + appendChild(createElementNS(namespaceURI, qualifiedName)); + } + } + + private static boolean isXMLIdentifierStart(char c) { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_'); + } + + private static boolean isXMLIdentifierPart(char c) { + return isXMLIdentifierStart(c) || (c >= '0' && c <= '9') || (c == '-') || (c == '.'); + } + + static boolean isXMLIdentifier(String s) { + if (s.length() == 0) { + return false; + } + + if (!isXMLIdentifierStart(s.charAt(0))) { + return false; + } + + for (int i = 1; i < s.length(); i++) { + if (!isXMLIdentifierPart(s.charAt(i))) { + return false; + } + } + + return true; + } + + /** + * Clones a node and (if requested) its children. The source node(s) may + * have been created by a different DocumentImpl or even DOM implementation. + * + * @param node The node to clone. + * @param deep If true, a deep copy is created (including all child nodes). + * + * @return The new node. + */ + Node cloneNode(Node node, boolean deep) throws DOMException { + Node target; + + switch (node.getNodeType()) { + case Node.ATTRIBUTE_NODE: { + Attr source = (Attr)node; + target = createAttributeNS(source.getNamespaceURI(), source.getLocalName()); + target.setPrefix(source.getPrefix()); + target.setNodeValue(source.getNodeValue()); + break; + } + case Node.CDATA_SECTION_NODE: { + CharacterData source = (CharacterData)node; + target = createCDATASection(source.getData()); + break; + } + case Node.COMMENT_NODE: { + Comment source = (Comment)node; + target = createComment(source.getData()); + break; + } + case Node.DOCUMENT_FRAGMENT_NODE: { + // Source is irrelevant in this case. + target = createDocumentFragment(); + break; + } + case Node.DOCUMENT_NODE: { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone a Document node"); + } + case Node.DOCUMENT_TYPE_NODE: { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone a DocumentType node"); + } + case Node.ELEMENT_NODE: { + Element source = (Element)node; + target = createElementNS(source.getNamespaceURI(), source.getLocalName()); + target.setPrefix(source.getPrefix()); + + NamedNodeMap map = source.getAttributes(); + for (int i = 0; i < map.getLength(); i++) { + Attr attr = (Attr)map.item(i); + ((Element)target).setAttributeNodeNS((Attr)cloneNode(attr, deep)); + } + break; + } + case Node.ENTITY_NODE: { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone an Entity node"); + } + case Node.ENTITY_REFERENCE_NODE: { + EntityReference source = (EntityReference)node; + target = createEntityReference(source.getNodeName()); + break; + } + case Node.NOTATION_NODE: { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone a Notation node"); + } + case Node.PROCESSING_INSTRUCTION_NODE: { + ProcessingInstruction source = (ProcessingInstruction)node; + target = createProcessingInstruction(source.getTarget(), source.getData()); + break; + } + case Node.TEXT_NODE: { + Text source = (Text)node; + target = createTextNode(source.getData()); + break; + } + default: { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone unknown node type " + node.getNodeType() + " (" + node.getClass().getSimpleName() + ")"); + } + } + + if (deep) { + NodeList list = node.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node child = cloneNode(list.item(i), deep); + target.appendChild(child); + } + } + + return target; + } + + public AttrImpl createAttribute(String name) throws DOMException { + return new AttrImpl(this, name); + } + + public Attr createAttributeNS(String namespaceURI, String qualifiedName) + throws DOMException { + return new AttrImpl(this, namespaceURI, qualifiedName); + } + + public CDATASection createCDATASection(String data) throws DOMException { + return new CDATASectionImpl(this, data); + } + + public Comment createComment(String data) { + return new CommentImpl(this, data); + } + + public DocumentFragment createDocumentFragment() { + return new DocumentFragmentImpl(this); + } + + public Element createElement(String tagName) throws DOMException { + return new ElementImpl(this, tagName); + } + + public Element createElementNS(String namespaceURI, String qualifiedName) + throws DOMException { + return new ElementImpl(this, namespaceURI, qualifiedName); + } + + public EntityReference createEntityReference(String name) + throws DOMException { + return new EntityReferenceImpl(this, name); + } + + public ProcessingInstruction createProcessingInstruction(String target, + String data) throws DOMException { + return new ProcessingInstructionImpl(this, target, data); + } + + public Text createTextNode(String data) { + return new TextImpl(this, data); + } + + public DocumentType getDoctype() { + for (int i = 0; i < children.size(); i++) { + if (children.get(i) instanceof DocumentType) { + return (DocumentType) children.get(i); + } + } + + return null; + } + + public Element getDocumentElement() { + for (int i = 0; i < children.size(); i++) { + if (children.get(i) instanceof Element) { + return (Element) children.get(i); + } + } + + return null; + } + + public Element getElementById(String elementId) { + ElementImpl root = (ElementImpl) getDocumentElement(); + + return (root == null ? null : root.getElementById(elementId)); + } + + public NodeList getElementsByTagName(String tagname) { + ElementImpl root = (ElementImpl) getDocumentElement(); + + return (root == null ? new NodeListImpl() + : root.getElementsByTagName(tagname)); + } + + public NodeList getElementsByTagNameNS(String namespaceURI, String localName) { + ElementImpl root = (ElementImpl) getDocumentElement(); + + return (root == null ? new NodeListImpl() : root.getElementsByTagNameNS( + namespaceURI, localName)); + } + + public DOMImplementation getImplementation() { + return domImplementation; + } + + @Override + public String getNodeName() { + return "#document"; + } + + @Override + public short getNodeType() { + return Node.DOCUMENT_NODE; + } + + public Node importNode(Node importedNode, boolean deep) throws DOMException { + return cloneNode(importedNode, deep); + } + + @Override + public Node insertChildAt(Node newChild, int index) throws DOMException { + // Make sure we have at most one root element and one DTD element. + if (newChild instanceof Element && getDocumentElement() != null) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, + "Only one root element allowed"); + } else if (newChild instanceof DocumentType && getDoctype() != null) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, + "Only one DOCTYPE element allowed"); + } + + return super.insertChildAt(newChild, index); + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java new file mode 100644 index 0000000..df40d4b --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.DOMException; +import org.w3c.dom.DocumentType; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class DocumentTypeImpl extends LeafNodeImpl implements DocumentType { + + private String qualifiedName; + + private String publicId; + + private String systemId; + + DocumentTypeImpl(DOMImplementationImpl impl, String qualifiedName, + String publicId, String systemId) { + super(null); + + if (qualifiedName == null || "".equals(qualifiedName)) { + throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName); + } + + int prefixSeparator = qualifiedName.lastIndexOf(":"); + if (prefixSeparator != -1) { + String prefix = qualifiedName.substring(0, prefixSeparator); + String localName = qualifiedName.substring(prefixSeparator + 1); + + if (!DocumentImpl.isXMLIdentifier(prefix)) { + throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName); + } + + if (!DocumentImpl.isXMLIdentifier(localName)) { + throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName); + } + } else { + if (!DocumentImpl.isXMLIdentifier(qualifiedName)) { + throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName); + } + } + + this.qualifiedName = qualifiedName; + this.publicId = publicId; + this.systemId = systemId; + } + + @Override + public String getNodeName() { + return qualifiedName; + } + + @Override + public short getNodeType() { + return Node.DOCUMENT_TYPE_NODE; + } + + public NamedNodeMap getEntities() { + // TODO Dummy. Implement this later, if at all (we're DOM level 2 only). + return null; + } + + public String getInternalSubset() { + // TODO Dummy. Implement this later, if at all (we're DOM level 2 only). + return null; + } + + public String getName() { + return qualifiedName; + } + + public NamedNodeMap getNotations() { + // TODO Dummy. Implement this later, if at all (we're DOM level 2 only). + return null; + } + + public String getPublicId() { + return publicId; + } + + public String getSystemId() { + return systemId; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java new file mode 100644 index 0000000..3b44ff3 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class ElementImpl extends InnerNodeImpl implements Element { + + private boolean namespaceAware; + + private String namespaceURI; + + private String prefix; + + private String localName; + + private List<AttrImpl> attributes = new ArrayList<AttrImpl>(); + + ElementImpl(DocumentImpl document, String namespaceURI, String qualifiedName) { + super(document); + + this.namespaceAware = true; + this.namespaceURI = namespaceURI; + + if (qualifiedName == null || "".equals(qualifiedName)) { + throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName); + } + + int p = qualifiedName.lastIndexOf(":"); + if (p != -1) { + setPrefix(qualifiedName.substring(0, p)); + qualifiedName = qualifiedName.substring(p + 1); + } + + if (!document.isXMLIdentifier(qualifiedName)) { + throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName); + } + + this.localName = qualifiedName; + } + + ElementImpl(DocumentImpl document, String name) { + super(document); + + this.namespaceAware = false; + + int p = name.lastIndexOf(":"); + if (p != -1) { + String prefix = name.substring(0, p); + String localName = name.substring(p + 1); + + if (!document.isXMLIdentifier(prefix) || !document.isXMLIdentifier(localName)) { + throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); + } + } else { + if (!document.isXMLIdentifier(name)) { + throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); + } + } + + this.localName = name; + } + + private int indexOfAttribute(String name) { + for (int i = 0; i < attributes.size(); i++) { + AttrImpl attr = attributes.get(i); + if (attr.matchesName(name, false)) { + return i; + } + } + + return -1; + } + + private int indexOfAttributeNS(String namespaceURI, String localName) { + for (int i = 0; i < attributes.size(); i++) { + AttrImpl attr = attributes.get(i); + if (attr.matchesNameNS(namespaceURI, localName, false)) { + return i; + } + } + + return -1; + } + + public String getAttribute(String name) { + Attr attr = getAttributeNode(name); + + if (attr == null) { + return ""; + } + + return attr.getValue(); + } + + public String getAttributeNS(String namespaceURI, String localName) { + Attr attr = getAttributeNodeNS(namespaceURI, localName); + + if (attr == null) { + return ""; + } + + return attr.getValue(); + } + + public Attr getAttributeNode(String name) { + int i = indexOfAttribute(name); + + if (i == -1) { + return null; + } + + return attributes.get(i); + } + + public Attr getAttributeNodeNS(String namespaceURI, String localName) { + int i = indexOfAttributeNS(namespaceURI, localName); + + if (i == -1) { + return null; + } + + return attributes.get(i); + } + + @Override + public NamedNodeMap getAttributes() { + return new ElementAttrNamedNodeMapImpl(); + } + + Element getElementById(String name) { + if (name.equals(getAttribute("id"))) { + return this; + } + + for (NodeImpl node : children) { + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element element = ((ElementImpl) node).getElementById(name); + if (element != null) { + return element; + } + } + } + + return null; + } + + public NodeList getElementsByTagName(String name) { + NodeListImpl list = new NodeListImpl(); + getElementsByTagName(list, name); + return list; + } + + void getElementsByTagName(NodeListImpl list, String name) { + if (matchesName(name, true)) { + list.add(this); + } + + for (NodeImpl node : children) { + if (node.getNodeType() == Node.ELEMENT_NODE) { + ((ElementImpl) node).getElementsByTagName(list, name); + } + } + } + + public NodeList getElementsByTagNameNS(String namespaceURI, String localName) { + NodeListImpl list = new NodeListImpl(); + getElementsByTagNameNS(list, namespaceURI, localName); + return list; + } + + void getElementsByTagNameNS(NodeListImpl list, String namespaceURI, + String localName) { + if (matchesNameNS(namespaceURI, localName, true)) { + list.add(this); + } + + for (NodeImpl node : children) { + if (node.getNodeType() == Node.ELEMENT_NODE) { + ((ElementImpl) node).getElementsByTagNameNS(list, namespaceURI, + localName); + } + } + } + + @Override + public String getLocalName() { + return namespaceAware ? localName : null; + } + + @Override + public String getNamespaceURI() { + return namespaceURI; + } + + @Override + public String getNodeName() { + return getTagName(); + } + + public short getNodeType() { + return Node.ELEMENT_NODE; + } + + @Override + public String getPrefix() { + return prefix; + } + + public String getTagName() { + return (prefix != null ? prefix + ":" : "") + localName; + } + + public boolean hasAttribute(String name) { + return indexOfAttribute(name) != -1; + } + + public boolean hasAttributeNS(String namespaceURI, String localName) { + return indexOfAttributeNS(namespaceURI, localName) != -1; + } + + @Override + public boolean hasAttributes() { + return !attributes.isEmpty(); + } + + public void removeAttribute(String name) throws DOMException { + int i = indexOfAttribute(name); + + if (i != -1) { + attributes.remove(i); + } + } + + public void removeAttributeNS(String namespaceURI, String localName) + throws DOMException { + int i = indexOfAttributeNS(namespaceURI, localName); + + if (i != -1) { + attributes.remove(i); + } + } + + public Attr removeAttributeNode(Attr oldAttr) throws DOMException { + AttrImpl oldAttrImpl = (AttrImpl) oldAttr; + + if (oldAttrImpl.getOwnerElement() != this) { + throw new DOMException(DOMException.NOT_FOUND_ERR, null); + } + + attributes.remove(oldAttr); + oldAttrImpl.ownerElement = null; + + return oldAttrImpl; + } + + public void setAttribute(String name, String value) throws DOMException { + Attr attr = getAttributeNode(name); + + if (attr == null) { + attr = document.createAttribute(name); + setAttributeNode(attr); + } + + attr.setValue(value); + } + + public void setAttributeNS(String namespaceURI, String qualifiedName, + String value) throws DOMException { + Attr attr = getAttributeNodeNS(namespaceURI, qualifiedName); + + if (attr == null) { + attr = document.createAttributeNS(namespaceURI, qualifiedName); + setAttributeNodeNS(attr); + } + + attr.setValue(value); + } + + public Attr setAttributeNode(Attr newAttr) throws DOMException { + AttrImpl newAttrImpl = (AttrImpl) newAttr; + + if (newAttrImpl.document != this.getOwnerDocument()) { + throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null); + } + + if (newAttrImpl.getOwnerElement() != null) { + throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, null); + } + + AttrImpl oldAttrImpl = null; + + int i = indexOfAttribute(newAttr.getName()); + if (i != -1) { + oldAttrImpl = attributes.get(i); + attributes.remove(i); + } + + attributes.add(newAttrImpl); + newAttrImpl.ownerElement = this; + + return oldAttrImpl; + } + + public Attr setAttributeNodeNS(Attr newAttr) throws DOMException { + AttrImpl newAttrImpl = (AttrImpl) newAttr; + + if (newAttrImpl.document != this.getOwnerDocument()) { + throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null); + } + + if (newAttrImpl.getOwnerElement() != null) { + throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, null); + } + + AttrImpl oldAttrImpl = null; + + int i = indexOfAttributeNS(newAttr.getNamespaceURI(), newAttr.getLocalName()); + if (i != -1) { + oldAttrImpl = attributes.get(i); + attributes.remove(i); + } + + attributes.add(newAttrImpl); + newAttrImpl.ownerElement = this; + + return oldAttrImpl; + } + + @Override + public void setPrefix(String prefix) { + if (!namespaceAware) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + + if (prefix != null) { + if (namespaceURI == null || !document.isXMLIdentifier(prefix)) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + + if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + } + + this.prefix = prefix; + } + + public class ElementAttrNamedNodeMapImpl implements NamedNodeMap { + + public int getLength() { + return ElementImpl.this.attributes.size(); + } + + private int indexOfItem(String name) { + return ElementImpl.this.indexOfAttribute(name); + } + + private int indexOfItemNS(String namespaceURI, String localName) { + return ElementImpl.this.indexOfAttributeNS(namespaceURI, localName); + } + + public Node getNamedItem(String name) { + return ElementImpl.this.getAttributeNode(name); + } + + public Node getNamedItemNS(String namespaceURI, String localName) { + return ElementImpl.this.getAttributeNodeNS(namespaceURI, localName); + } + + public Node item(int index) { + return ElementImpl.this.attributes.get(index); + } + + public Node removeNamedItem(String name) throws DOMException { + int i = indexOfItem(name); + + if (i == -1) { + throw new DOMException(DOMException.NOT_FOUND_ERR, null); + } + + return ElementImpl.this.attributes.remove(i); + } + + public Node removeNamedItemNS(String namespaceURI, String localName) + throws DOMException { + int i = indexOfItemNS(namespaceURI, localName); + + if (i == -1) { + throw new DOMException(DOMException.NOT_FOUND_ERR, null); + } + + return ElementImpl.this.attributes.remove(i); + } + + public Node setNamedItem(Node arg) throws DOMException { + if (!(arg instanceof Attr)) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + return ElementImpl.this.setAttributeNode((Attr)arg); + } + + public Node setNamedItemNS(Node arg) throws DOMException { + if (!(arg instanceof Attr)) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + return ElementImpl.this.setAttributeNodeNS((Attr)arg); + } + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/EntityImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/EntityImpl.java new file mode 100644 index 0000000..463e863 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/EntityImpl.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Document; +import org.w3c.dom.Entity; +import org.w3c.dom.Node; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class EntityImpl extends NodeImpl implements Entity { + + private String notationName; + + private String publicID; + + private String systemID; + + EntityImpl(DocumentImpl document, String notationName, String publicID, + String systemID) { + super(document); + this.notationName = notationName; + this.publicID = publicID; + this.systemID = systemID; + } + + @Override + public String getNodeName() { + return getNotationName(); + } + + @Override + public short getNodeType() { + return Node.ENTITY_NODE; + } + + public String getNotationName() { + return notationName; + } + + public String getPublicId() { + return publicID; + } + + public String getSystemId() { + return systemID; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/EntityReferenceImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/EntityReferenceImpl.java new file mode 100644 index 0000000..f612a15 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/EntityReferenceImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Document; +import org.w3c.dom.EntityReference; +import org.w3c.dom.Node; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class EntityReferenceImpl extends LeafNodeImpl implements EntityReference { + + private String name; + + EntityReferenceImpl(DocumentImpl document, String name) { + super(document); + this.name = name; + } + + @Override + public String getNodeName() { + return name; + } + + @Override + public short getNodeType() { + return Node.ENTITY_REFERENCE_NODE; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java new file mode 100644 index 0000000..f71d289 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + * <p> + * This class represents a Node that has a parent Node as well as (potentially) + * a number of children. + */ +public abstract class InnerNodeImpl extends LeafNodeImpl { + + // Maintained by LeafNodeImpl and ElementImpl. + List<LeafNodeImpl> children = new ArrayList<LeafNodeImpl>(); + + public InnerNodeImpl(DocumentImpl document) { + super(document); + } + + public Node appendChild(Node newChild) throws DOMException { + return insertChildAt(newChild, children.size()); + } + + public NodeList getChildNodes() { + NodeListImpl list = new NodeListImpl(); + + for (NodeImpl node : children) { + list.add(node); + } + + return list; + } + + public Node getFirstChild() { + return (!children.isEmpty() ? children.get(0) : null); + } + + public Node getLastChild() { + return (!children.isEmpty() ? children.get(children.size() - 1) : null); + } + + public Node getNextSibling() { + if (parent == null || index >= parent.children.size()) { + return null; + } + + return parent.children.get(index + 1); + } + + public boolean hasChildNodes() { + return children.size() != 0; + } + + public Node insertBefore(Node newChild, Node refChild) throws DOMException { + LeafNodeImpl refChildImpl = (LeafNodeImpl) refChild; + + if (refChildImpl.document != document) { + throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null); + } + + if (refChildImpl.parent != this) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + return insertChildAt(newChild, refChildImpl.index); + } + + /** + * Inserts a new child node into this node at a given position. If the new + * node is already child of another node, it is first removed from there. + * This method is the generalization of the appendChild() and insertBefore() + * methods. + * + * @param newChild The new child node to add. + * @param index The index at which to insert the new child node. + * + * @return The node added. + * + * @throws DOMException If the attempted operation violates the XML/DOM + * well-formedness rules. + */ + public Node insertChildAt(Node newChild, int index) throws DOMException { + LeafNodeImpl newChildImpl = (LeafNodeImpl) newChild; + + if (document != null && newChildImpl.document != null && newChildImpl.document != document) { + throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null); + } + + if (newChildImpl.isParentOf(this)) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + if (newChildImpl.parent != null) { + int oldIndex = newChildImpl.index; + newChildImpl.parent.children.remove(oldIndex); + newChildImpl.parent.refreshIndices(oldIndex); + } + + children.add(index, newChildImpl); + newChildImpl.parent = this; + refreshIndices(index); + + return newChild; + } + + public boolean isParentOf(Node node) { + LeafNodeImpl nodeImpl = (LeafNodeImpl) node; + + while (nodeImpl != null) { + if (nodeImpl == this) { + return true; + } + + nodeImpl = nodeImpl.parent; + } + + return false; + } + + @Override + public void normalize() { + Node nextNode = null; + + for (int i = children.size() - 1; i >= 0; i--) { + Node thisNode = children.get(i); + + thisNode.normalize(); + + if (thisNode.getNodeType() == Node.TEXT_NODE) { + if (nextNode != null && nextNode.getNodeType() == Node.TEXT_NODE) { + ((Text)thisNode).setData(thisNode.getNodeValue() + nextNode.getNodeValue()); + removeChild(nextNode); + } + + if ("".equals(thisNode.getNodeValue())) { + removeChild(thisNode); + nextNode = null; + } else { + nextNode = thisNode; + } + } + } + } + + private void refreshIndices(int fromIndex) { + for (int i = fromIndex; i < children.size(); i++) { + children.get(i).index = i; + } + } + + public Node removeChild(Node oldChild) throws DOMException { + LeafNodeImpl oldChildImpl = (LeafNodeImpl) oldChild; + + if (oldChildImpl.document != document) { + throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null); + } + + if (oldChildImpl.parent != this) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + int index = oldChildImpl.index; + children.remove(index); + oldChildImpl.parent = null; + refreshIndices(index); + + return oldChild; + } + + public Node replaceChild(Node newChild, Node oldChild) throws DOMException { + LeafNodeImpl oldChildImpl = (LeafNodeImpl) oldChild; + LeafNodeImpl newChildImpl = (LeafNodeImpl) newChild; + + if (oldChildImpl.document != document + || newChildImpl.document != document) { + throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null); + } + + if (oldChildImpl.parent != this || newChildImpl.isParentOf(this)) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + int index = oldChildImpl.index; + children.set(index, newChildImpl); + oldChildImpl.parent = null; + newChildImpl.parent = this; + refreshIndices(index); + + return oldChildImpl; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/LeafNodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/LeafNodeImpl.java new file mode 100644 index 0000000..5f9698e --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/LeafNodeImpl.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + * <p> + * This class represents a Node that has a parent Node, but no children. + */ +public abstract class LeafNodeImpl extends NodeImpl { + + // Maintained by InnerNodeImpl. + InnerNodeImpl parent; + + // Maintained by InnerNodeImpl. + int index; + + LeafNodeImpl(DocumentImpl document) { + super(document); + } + + public Node getNextSibling() { + if (parent == null || index + 1 >= parent.children.size()) { + return null; + } + + return parent.children.get(index + 1); + } + + public Node getParentNode() { + return parent; + } + + public Node getPreviousSibling() { + if (parent == null || index == 0) { + return null; + } + + return parent.children.get(index - 1); + } + + boolean isParentOf(Node node) { + return false; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NamedNodeMapImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NamedNodeMapImpl.java new file mode 100644 index 0000000..0952d83 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NamedNodeMapImpl.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +import java.util.ArrayList; +import java.util.List; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class NamedNodeMapImpl implements NamedNodeMap { + + private Class<?> type; + + private List<NodeImpl> list; + + NamedNodeMapImpl(Class<?> type) { + list = new ArrayList<NodeImpl>(); + this.type = type; + } + + NamedNodeMapImpl(List<NodeImpl> list, Class<?> type) { + this.list = list; + this.type = type; + } + + public int getLength() { + return list.size(); + } + + private int indexOfItem(String name) { + for (int i = 0; i < list.size(); i++) { + NodeImpl node = list.get(i); + if (node.matchesName(name, false)) { + return i; + } + } + + return -1; + } + + private int indexOfItemNS(String namespaceURI, String localName) { + for (int i = 0; i < list.size(); i++) { + NodeImpl node = list.get(i); + if (node.matchesNameNS(namespaceURI, localName, false)) { + return i; + } + } + + return -1; + } + + public Node getNamedItem(String name) { + int i = indexOfItem(name); + + return (i == -1 ? null : item(i)); + } + + public Node getNamedItemNS(String namespaceURI, String localName) { + int i = indexOfItemNS(namespaceURI, localName); + + return (i == -1 ? null : item(i)); + } + + public Node item(int index) { + return list.get(index); + } + + public Node removeNamedItem(String name) throws DOMException { + int i = indexOfItem(name); + + if (i == -1) { + throw new DOMException(DOMException.NOT_FOUND_ERR, null); + } + + return list.remove(i); + } + + public Node removeNamedItemNS(String namespaceURI, String localName) + throws DOMException { + int i = indexOfItemNS(namespaceURI, localName); + + if (i == -1) { + throw new DOMException(DOMException.NOT_FOUND_ERR, null); + } + + return list.remove(i); + } + + public Node setNamedItem(Node arg) throws DOMException { + // Ensure we only accept nodes of the correct type. + if (!type.isAssignableFrom(arg.getClass())) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + // All nodes in the map must belong to the same document. + if (list.size() != 0) { + Document document = list.get(0).getOwnerDocument(); + + if (document != null && arg.getOwnerDocument() != document) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + } + +// TODO Theoretically we should ensure that the nodes don't have a parent. +// if (newAttrImpl.getOwnerElement() != null) { +// throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, null); +// } + + int i = indexOfItem(arg.getNodeName()); + + if (i != -1) { + list.remove(i); + } + + list.add((NodeImpl)arg); + return arg; + } + + public Node setNamedItemNS(Node arg) throws DOMException { + // Ensure we only accept nodes of the correct type. + if (!type.isAssignableFrom(arg.getClass())) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + // All nodes in the map must belong to the same document. + if (list.size() != 0) { + Document document = list.get(0).getOwnerDocument(); + + if (document != null && arg.getOwnerDocument() != document) { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + } + +// TODO Theoretically we should ensure that the nodes don't have a parent. +// if (newAttrImpl.getOwnerElement() != null) { +// throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, null); +// } + + int i = indexOfItemNS(arg.getNamespaceURI(), arg.getLocalName()); + + if (i != -1) { + list.remove(i); + } + + list.add((NodeImpl)arg); + return arg; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java new file mode 100644 index 0000000..ca6fb8f --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + * <p> + * This class represents a Node that has neither a parent nor children. + */ +public abstract class NodeImpl implements Node { + + private static final NodeList EMPTY_LIST = new NodeListImpl(); + + // Maintained by InnerNodeImpl and ElementImpl. + DocumentImpl document; + + NodeImpl(DocumentImpl document) { + this.document = document; + } + + public Node appendChild(Node newChild) throws DOMException { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + public Node cloneNode(boolean deep) { + return document.cloneNode(this, deep); + } + + public NamedNodeMap getAttributes() { + return null; + } + + public NodeList getChildNodes() { + return EMPTY_LIST; + } + + public Node getFirstChild() { + return null; + } + + public Node getLastChild() { + return null; + } + + public String getLocalName() { + return null; + } + + public String getNamespaceURI() { + return null; + } + + public Node getNextSibling() { + return null; + } + + public String getNodeName() { + return null; + } + + public abstract short getNodeType(); + + public String getNodeValue() throws DOMException { + return null; + } + + public Document getOwnerDocument() { + return document; + } + + public Node getParentNode() { + return null; + } + + public String getPrefix() { + return null; + } + + public Node getPreviousSibling() { + return null; + } + + public boolean hasAttributes() { + return false; + } + + public boolean hasChildNodes() { + return false; + } + + public Node insertBefore(Node newChild, Node refChild) throws DOMException { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + public boolean isSupported(String feature, String version) { + return DOMImplementationImpl.getInstance().hasFeature(feature, version); + } + + public void normalize() { + } + + public Node removeChild(Node oldChild) throws DOMException { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + public Node replaceChild(Node newChild, Node oldChild) throws DOMException { + throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); + } + + public void setNodeValue(String nodeValue) throws DOMException { + } + + public void setPrefix(String prefix) throws DOMException { + } + + /** + * Checks whether a required string matches an actual string. This utility + * method is used for comparing namespaces and such. It takes into account + * null arguments and the "*" special case. + * + * @param required The required string. + * @param actual The actual string. + * @return True if and only if the actual string matches the required one. + */ + private static boolean matchesName(String required, String actual, boolean wildcard) { + if (wildcard && "*".equals(required)) { + return true; + } + + if (required == null) { + return (actual == null); + } + + return required.equals(actual); + } + + /** + * Checks whether this node's name matches a required name. It takes into + * account null arguments and the "*" special case. + * + * @param name The required name. + * @param wildcard TODO + * @return True if and only if the actual name matches the required one. + */ + public boolean matchesName(String name, boolean wildcard) { + return matchesName(name, getNodeName(), wildcard); + } + + /** + * Checks whether this node's namespace and local name match a required + * pair of namespace and local name. It takes into account null arguments + * and the "*" special case. + * + * @param namespaceURI The required namespace. + * @param localName The required local name. + * @param wildcard TODO + * @return True if and only if the actual namespace and local name match + * the required pair of namespace and local name. + */ + public boolean matchesNameNS(String namespaceURI, String localName, boolean wildcard) { + return matchesName(namespaceURI, getNamespaceURI(), wildcard) && matchesName(localName, getLocalName(), wildcard); + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeListImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeListImpl.java new file mode 100644 index 0000000..caa56af --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeListImpl.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.util.ArrayList; +import java.util.List; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class NodeListImpl implements NodeList { + + private List<NodeImpl> children; + + NodeListImpl() { + children = new ArrayList<NodeImpl>(); + } + + NodeListImpl(List<NodeImpl> list) { + children = list; + } + + void add(NodeImpl node) { + children.add(node); + } + + public int getLength() { + return children.size(); + } + + public Node item(int index) { + if (index >= children.size()) { + return null; + } else { + return children.get(index); + } + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NotationImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NotationImpl.java new file mode 100644 index 0000000..4d91d75 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NotationImpl.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.Notation; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class NotationImpl extends LeafNodeImpl implements Notation { + + private String notationName; + + private String publicID; + + private String systemID; + + NotationImpl(DocumentImpl document, String notationName, String publicID, + String systemID) { + super(document); + } + + @Override + public String getNodeName() { + return notationName; + } + + @Override + public short getNodeType() { + return Node.NOTATION_NODE; + } + + public String getPublicId() { + return publicID; + } + + public String getSystemId() { + return systemID; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/ProcessingInstructionImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/ProcessingInstructionImpl.java new file mode 100644 index 0000000..c3610d5 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/ProcessingInstructionImpl.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class ProcessingInstructionImpl extends LeafNodeImpl implements + ProcessingInstruction { + + private String target; + + private String data; + + ProcessingInstructionImpl(DocumentImpl document, String target, String data) { + super(document); + this.target = target; + this.data = data; + } + + public String getData() { + return data; + } + + @Override + public String getNodeName() { + return target; + } + + @Override + public short getNodeType() { + return Node.PROCESSING_INSTRUCTION_NODE; + } + + @Override + public String getNodeValue() { + return data; + } + + public String getTarget() { + return target; + } + + public void setData(String data) throws DOMException { + this.data = data; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java new file mode 100644 index 0000000..3553546 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.dom; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.Text; + +/** + * Provides a straightforward implementation of the corresponding W3C DOM + * interface. The class is used internally only, thus only notable members that + * are not in the original interface are documented (the W3C docs are quite + * extensive). Hope that's ok. + * <p> + * Some of the fields may have package visibility, so other classes belonging to + * the DOM implementation can easily access them while maintaining the DOM tree + * structure. + */ +public class TextImpl extends CharacterDataImpl implements Text { + + TextImpl(DocumentImpl document, String data) { + super(document, data); + } + + @Override + public String getNodeName() { + return "#text"; + } + + @Override + public short getNodeType() { + return Node.TEXT_NODE; + } + + @Override + public String getNodeValue() { + return getData(); + } + + public Text splitText(int offset) throws DOMException { + Text newText = getOwnerDocument().createTextNode( + substringData(offset, getLength() - offset)); + deleteData(0, offset); + + Node refNode = getNextSibling(); + if (refNode == null) { + getParentNode().appendChild(newText); + } else { + getParentNode().insertBefore(newText, refNode); + } + + return this; + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl.java new file mode 100644 index 0000000..4b8eef3 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.parsers; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +/** + * Provides a straightforward DocumentBuilderFactory implementation based on + * XMLPull/KXML. The class is used internally only, thus only notable members + * that are not already in the abstract superclass are documented. Hope that's + * ok. + */ +public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { + + private static final String NAMESPACES = + "http://xml.org/sax/features/namespaces"; + + private static final String VALIDATION = + "http://xml.org/sax/features/validation"; + + @Override + public Object getAttribute(String name) throws IllegalArgumentException { + throw new IllegalArgumentException(name); + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException { + if (name == null) { + throw new NullPointerException(); + } + + if (NAMESPACES.equals(name)) { + return isNamespaceAware(); + } else if (VALIDATION.equals(name)) { + return isValidating(); + } else { + throw new ParserConfigurationException(name); + } + } + + @Override + public DocumentBuilder newDocumentBuilder() + throws ParserConfigurationException { + if (isValidating()) { + throw new ParserConfigurationException( + "No validating DocumentBuilder implementation available"); + } + + /** + * TODO If Android is going to support a different DocumentBuilder + * implementations, this should be wired here. If we wanted to + * allow different implementations, these could be distinguished by + * a special feature (like http://www.org.apache.harmony.com/xml/expat) + * or by throwing the full SPI monty at it. + */ + DocumentBuilderImpl builder = new DocumentBuilderImpl(); + + builder.setIgnoreComments(isIgnoringComments()); + builder.setIgnoreElementContentWhitespace( + isIgnoringElementContentWhitespace()); + builder.setNamespaceAware(isNamespaceAware()); + + // TODO What about expandEntityReferences? + + return builder; + } + + @Override + public void setAttribute(String name, Object value) + throws IllegalArgumentException { + throw new IllegalArgumentException(name); + } + + @Override + public void setFeature(String name, boolean value) + throws ParserConfigurationException { + if (name == null) { + throw new NullPointerException(); + } + + if (NAMESPACES.equals(name)) { + setNamespaceAware(value); + } else if (VALIDATION.equals(name)) { + setValidating(value); + } else { + throw new ParserConfigurationException(name); + } + } + +} diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java new file mode 100644 index 0000000..f831c8b --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.parsers; + +import java.io.IOException; +import java.util.StringTokenizer; + +import javax.xml.parsers.DocumentBuilder; + +import org.kxml2.io.KXmlParser; +import org.w3c.dom.Attr; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.LocatorImpl; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import org.apache.harmony.xml.dom.DOMImplementationImpl; + +/** + * Provides a straightforward DocumentBuilder implementation based on + * XMLPull/KXML. The class is used internally only, thus only notable members + * that are not already in the abstract superclass are documented. Hope that's + * ok. + */ +class DocumentBuilderImpl extends DocumentBuilder { + + private static DOMImplementation dom = DOMImplementationImpl.getInstance(); + + private EntityResolver entityResolver; + + private ErrorHandler errorHandler; + + private boolean ignoreComments; + + private boolean ignoreElementContentWhitespace; + + private boolean namespaceAware; + + DocumentBuilderImpl() { + // Do nothing. + } + + @Override + public DOMImplementation getDOMImplementation() { + return dom; + } + + /** + * Reflects whether this DocumentBuilder is configured to ignore comments. + * + * @return True if and only if comments are ignored. + */ + public boolean isIgnoringComments() { + return ignoreComments; + } + + /** + * Reflects whether this DocumentBuilder is configured to ignore element + * content whitespace. + * + * @return True if and only if whitespace element content is ignored. + */ + public boolean isIgnoringElementContentWhitespace() { + return ignoreElementContentWhitespace; + } + + @Override + public boolean isNamespaceAware() { + return namespaceAware; + } + + @Override + public boolean isValidating() { + return false; + } + + @Override + public Document newDocument() { + return dom.createDocument(null, null, null); + } + + @Override + public Document parse(InputSource source) throws SAXException, IOException { + if (source == null) { + throw new IllegalArgumentException(); + } + + Document document = newDocument(); + + try { + XmlPullParser parser = new KXmlParser(); + + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, + namespaceAware); + + if (source.getByteStream() != null) { + parser.setInput(source.getByteStream(), source.getEncoding()); + } else if (source.getCharacterStream() != null) { + parser.setInput(source.getCharacterStream()); + } else { + // TODO Accept other sources as well? + throw new SAXParseException( + "InputSource needs either stream or reader", null); + } + + if(parser.nextToken() == XmlPullParser.END_DOCUMENT) { + throw new SAXParseException( + "Unexpected end of document", null); + } + + parse(parser, document, document, XmlPullParser.END_DOCUMENT); + + parser.require(XmlPullParser.END_DOCUMENT, null, null); + } catch (XmlPullParserException ex) { + if(ex.getDetail() instanceof IOException) { + throw (IOException)ex.getDetail(); + } + if(ex.getDetail() instanceof RuntimeException) { + throw (RuntimeException)ex.getDetail(); + } + + LocatorImpl locator = new LocatorImpl(); + + locator.setPublicId(source.getPublicId()); + locator.setSystemId(source.getSystemId()); + locator.setLineNumber(ex.getLineNumber()); + locator.setColumnNumber(ex.getColumnNumber()); + + SAXParseException newEx = new SAXParseException(ex.getMessage(), + locator); + + if (errorHandler != null) { + errorHandler.error(newEx); + } + + throw newEx; + } + + return document; + } + + /** + * Implements the whole parsing of the XML document. The XML pull parser is + * actually more of a tokenizer, and we are doing a classical recursive + * descent parsing (the method invokes itself for XML elements). Our + * approach to parsing does accept some illegal documents (more than one + * root element, for example). The assumption is that the DOM implementation + * throws the proper exceptions in these cases. + * + * @param parser The XML pull parser we're reading from. + * @param document The document we're building. + * @param node The node we're currently on (initially the document itself). + * @param endToken The token that will end this recursive call. Either + * XmlPullParser.END_DOCUMENT or XmlPullParser.END_TAG. + * + * @throws XmlPullParserException If a parsing error occurs. + * @throws IOException If a general IO error occurs. + */ + private void parse(XmlPullParser parser, Document document, Node node, + int endToken) throws XmlPullParserException, IOException { + + int token = parser.getEventType(); + + /* + * The main parsing loop. The precondition is that we are already on the + * token to be processed. This holds for each iteration of the loop, so + * the inner statements have to ensure that (in particular the recursive + * call). + */ + while (token != endToken && token != XmlPullParser.END_DOCUMENT) { + if (token == XmlPullParser.PROCESSING_INSTRUCTION) { + /* + * Found a processing instructions. We need to split the token + * text at the first whitespace character. + */ + String text = parser.getText(); + + int dot = text.indexOf(' '); + + String target = (dot != -1 ? text.substring(0, dot) : text); + String data = (dot != -1 ? text.substring(dot + 1) : ""); + + node.appendChild(document.createProcessingInstruction(target, + data)); + } else if (token == XmlPullParser.DOCDECL) { + /* + * Found a document type declaration. Unfortunately KXML doesn't + * have the necessary details. Do we parse it ourselves, or do + * we silently ignore it, since it isn't mandatory in DOM 2 + * anyway? + */ + StringTokenizer tokenizer = new StringTokenizer(parser.getText()); + if (tokenizer.hasMoreTokens()) { + String name = tokenizer.nextToken(); + String pubid = null; + String sysid = null; + + if (tokenizer.hasMoreTokens()) { + String text = tokenizer.nextToken(); + + if ("SYSTEM".equals(text)) { + if (tokenizer.hasMoreTokens()) { + sysid = tokenizer.nextToken(); + } + } else if ("PUBLIC".equals(text)) { + if (tokenizer.hasMoreTokens()) { + pubid = tokenizer.nextToken(); + } + if (tokenizer.hasMoreTokens()) { + sysid = tokenizer.nextToken(); + } + } + } + + if (pubid != null && pubid.length() >= 2 && pubid.startsWith("\"") && pubid.endsWith("\"")) { + pubid = pubid.substring(1, pubid.length() - 1); + } + + if (sysid != null && sysid.length() >= 2 && sysid.startsWith("\"") && sysid.endsWith("\"")) { + sysid = sysid.substring(1, sysid.length() - 1); + } + + document.appendChild(dom.createDocumentType(name, pubid, sysid)); + } + + } else if (token == XmlPullParser.COMMENT) { + /* + * Found a comment. We simply take the token text, but we only + * create a node if the client wants to see comments at all. + */ + if (!ignoreComments) { + node.appendChild(document.createComment(parser.getText())); + } + } else if (token == XmlPullParser.IGNORABLE_WHITESPACE) { + /* + * Found some ignorable whitespace. We simply take the token + * text, but we only create a node if the client wants to see + * whitespace at all. + */ + if (!ignoreElementContentWhitespace) { + node.appendChild(document.createTextNode(parser.getText())); + } + } else if (token == XmlPullParser.TEXT) { + /* + * Found a piece of text. That's the easiest case. We simply + * take it and create a corresponding node. + */ + node.appendChild(document.createTextNode(parser.getText())); + } else if (token == XmlPullParser.CDSECT) { + /* + * Found a CDATA section. That's also trivial. We simply + * take it and create a corresponding node. + */ + node.appendChild(document.createCDATASection(parser.getText())); + } else if (token == XmlPullParser.ENTITY_REF) { + /* + * Found an entity reference. If an entity resolver is + * installed, we replace it by text (if possible). Otherwise we + * add an entity reference node. + */ + String entity = parser.getName(); + + if (entityResolver != null) { + // TODO Implement this... + } + + String replacement = resolveStandardEntity(entity); + if (replacement != null) { + node.appendChild(document.createTextNode(replacement)); + } else { + node.appendChild(document.createEntityReference(entity)); + } + } else if (token == XmlPullParser.START_TAG) { + /* + * Found an element start tag. We create an element node with + * the proper info and attributes. We then invoke parse() + * recursively to handle the next level of nesting. When we + * return from this call, we check that we are on the proper + * element end tag. The whole handling differs somewhat + * depending on whether the parser is namespace-aware or not. + */ + if (namespaceAware) { + // Collect info for element node + String namespace = parser.getNamespace(); + String name = parser.getName(); + String prefix = parser.getPrefix(); + + if ("".equals(namespace)) { + namespace = null; + } + + // Create element node and wire it correctly + Element element = document.createElementNS(namespace, name); + element.setPrefix(prefix); + node.appendChild(element); + + for (int i = 0; i < parser.getAttributeCount(); i++) { + // Collect info for a single attribute node + String attrNamespace = parser.getAttributeNamespace(i); + String attrPrefix = parser.getAttributePrefix(i); + String attrName = parser.getAttributeName(i); + String attrValue = parser.getAttributeValue(i); + + if ("".equals(attrNamespace)) { + attrNamespace = null; + } + + // Create attribute node and wire it correctly + Attr attr = document.createAttributeNS(attrNamespace, attrName); + attr.setPrefix(attrPrefix); + attr.setValue(attrValue); + element.setAttributeNodeNS(attr); + } + + // Recursive descent + token = parser.nextToken(); + parse(parser, document, element, XmlPullParser.END_TAG); + + // Expect the element's end tag here + parser.require(XmlPullParser.END_TAG, namespace, name); + + } else { + // Collect info for element node + String name = parser.getName(); + + // Create element node and wire it correctly + Element element = document.createElement(name); + node.appendChild(element); + + for (int i = 0; i < parser.getAttributeCount(); i++) { + // Collect info for a single attribute node + String attrName = parser.getAttributeName(i); + String attrValue = parser.getAttributeValue(i); + + // Create attribute node and wire it correctly + Attr attr = document.createAttribute(attrName); + attr.setValue(attrValue); + element.setAttributeNode(attr); + } + + // Recursive descent + token = parser.nextToken(); + parse(parser, document, element, XmlPullParser.END_TAG); + + // Expect the element's end tag here + parser.require(XmlPullParser.END_TAG, "", name); + } + } + + token = parser.nextToken(); + } + } + + @Override + public void setEntityResolver(EntityResolver resolver) { + entityResolver = resolver; + } + + @Override + public void setErrorHandler(ErrorHandler handler) { + errorHandler = handler; + } + + /** + * Controls whether this DocumentBuilder ignores comments. + * + * @param value Turns comment ignorance on or off. + */ + public void setIgnoreComments(boolean value) { + ignoreComments = value; + } + + /** + * Controls whether this DocumentBuilder ignores element content whitespace. + * + * @param value Turns element whitespace content ignorance on or off. + */ + public void setIgnoreElementContentWhitespace(boolean value) { + ignoreElementContentWhitespace = value; + } + + /** + * Controls whether this DocumentBuilder is namespace-aware. + * + * @param value Turns namespace awareness on or off. + */ + public void setNamespaceAware(boolean value) { + namespaceAware = value; + } + + /** + * Resolves one of the five standard XML entities. + * + * @param entity The name of the entity to resolve, not including + * the ampersand or the semicolon. + * + * @return The proper replacement, or null, if the entity is unknown. + */ + private String resolveStandardEntity(String entity) { + if ("lt".equals(entity)) { + return "<"; + } else if ("gt".equals(entity)) { + return ">"; + } else if ("amp".equals(entity)) { + return "&"; + } else if ("apos".equals(entity)) { + return "'"; + } else if ("quot".equals(entity)) { + return "\""; + } else { + return null; + } + } +} diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserFactoryImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserFactoryImpl.java new file mode 100644 index 0000000..6846216 --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserFactoryImpl.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.parsers; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.SAXNotRecognizedException; + +/** + * Provides a straightforward SAXParserFactory implementation based on + * Expat. The class is used internally only, thus only notable members + * that are not already in the abstract superclass are documented. + */ +public class SAXParserFactoryImpl extends SAXParserFactory { + + private static final String NAMESPACES + = "http://xml.org/sax/features/namespaces"; + + private static final String VALIDATION + = "http://xml.org/sax/features/validation"; + + private Map<String, Boolean> features = new HashMap<String, Boolean>(); + + @Override + public boolean getFeature(String name) throws SAXNotRecognizedException { + if (name == null) { + throw new NullPointerException(); + } + + if (!name.startsWith("http://xml.org/sax/features/")) { + throw new SAXNotRecognizedException(name); + } + + return Boolean.TRUE.equals(features.get(name)); + } + + @Override + public boolean isNamespaceAware() { + try { + return getFeature(NAMESPACES); + } catch (SAXNotRecognizedException ex) { + throw new AssertionError(ex); + } + } + + @Override + public boolean isValidating() { + try { + return getFeature(VALIDATION); + } catch (SAXNotRecognizedException ex) { + throw new AssertionError(ex); + } + } + + @Override + public SAXParser newSAXParser() throws ParserConfigurationException { + if (isValidating()) { + throw new ParserConfigurationException( + "No validating SAXParser implementation available"); + } + + try { + return new SAXParserImpl(features); + } catch (Exception ex) { + throw new ParserConfigurationException(ex.toString()); + } + } + + @Override + public void setFeature(String name, boolean value) throws SAXNotRecognizedException { + if (name == null) { + throw new NullPointerException(); + } + + if (!name.startsWith("http://xml.org/sax/features/")) { + throw new SAXNotRecognizedException(name); + } + + if (value) { + features.put(name, Boolean.TRUE); + } else { + // This is needed to disable features that are enabled by default. + features.put(name, Boolean.FALSE); + } + } + + @Override + public void setNamespaceAware(boolean value) { + try { + setFeature(NAMESPACES, value); + } catch (SAXNotRecognizedException ex) { + throw new AssertionError(ex); + } + } + + @Override + public void setValidating(boolean value) { + try { + setFeature(VALIDATION, value); + } catch (SAXNotRecognizedException ex) { + throw new AssertionError(ex); + } + } +} diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserImpl.java new file mode 100644 index 0000000..b3af61f --- /dev/null +++ b/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserImpl.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml.parsers; + +import org.apache.harmony.xml.ExpatReader; + +import java.util.Map; + +import javax.xml.parsers.SAXParser; + +import org.xml.sax.Parser; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderAdapter; + +/** + * Provides a straightforward SAXParser implementation based on ExpatReader. + * The class is used internally only, thus only notable members that are not + * already in the abstract superclass are documented. Hope that's ok. + */ +class SAXParserImpl extends SAXParser { + + private XMLReader reader; + + private Parser parser; + + SAXParserImpl(Map<String, Boolean> features) + throws SAXNotRecognizedException, SAXNotSupportedException { + reader = new ExpatReader(); + + for (Map.Entry<String,Boolean> entry : features.entrySet()) { + reader.setFeature(entry.getKey(), entry.getValue()); + } + } + + @Override + public Parser getParser() { + if (parser == null) { + parser = new XMLReaderAdapter(reader); + } + + return parser; + } + + @Override + public Object getProperty(String name) throws SAXNotRecognizedException, + SAXNotSupportedException { + return reader.getProperty(name); + } + + @Override + public XMLReader getXMLReader() { + return reader; + } + + @Override + public boolean isNamespaceAware() { + try { + return reader.getFeature("http://xml.org/sax/features/namespaces"); + } catch (SAXException ex) { + return false; + } + } + + @Override + public boolean isValidating() { + return false; + } + + @Override + public void setProperty(String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException { + reader.setProperty(name, value); + } +} diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java new file mode 100644 index 0000000..0727bc7 --- /dev/null +++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java @@ -0,0 +1,1440 @@ +/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ + +// Contributors: Paul Hackenberger (unterminated entity handling in relaxed mode) + +package org.kxml2.io; + +import java.io.*; +import java.util.*; + +import org.xmlpull.v1.*; + +/** A simple, pull based XML parser. This classe replaces the kXML 1 + XmlParser class and the corresponding event classes. */ + +public class KXmlParser implements XmlPullParser { + + private Object location; + static final private String UNEXPECTED_EOF = "Unexpected EOF"; + static final private String ILLEGAL_TYPE = "Wrong event type"; + static final private int LEGACY = 999; + static final private int XML_DECL = 998; + + // general + + private String version; + private Boolean standalone; + + private boolean processNsp; + private boolean relaxed; + private Hashtable entityMap; + private int depth; + private String[] elementStack = new String[16]; + private String[] nspStack = new String[8]; + private int[] nspCounts = new int[4]; + + // source + + private Reader reader; + private String encoding; + private char[] srcBuf; + + private int srcPos; + private int srcCount; + + private int line; + private int column; + + // txtbuffer + + private char[] txtBuf = new char[128]; + private int txtPos; + + // Event-related + + private int type; + //private String text; + private boolean isWhitespace; + private String namespace; + private String prefix; + private String name; + + private boolean degenerated; + private int attributeCount; + private String[] attributes = new String[16]; + private int stackMismatch = 0; + private String error; + + /** + * A separate peek buffer seems simpler than managing + * wrap around in the first level read buffer */ + + private int[] peek = new int[2]; + private int peekCount; + private boolean wasCR; + + private boolean unresolved; + private boolean token; + + public KXmlParser() { + // BEGIN android-changed + // We don't have a Runtime class at this time. + // srcBuf = + // new char[Runtime.getRuntime().freeMemory() >= 1048576 ? 8192 : 128]; + srcBuf = new char[8192]; + // END android-changed + } + + private final boolean isProp(String n1, boolean prop, String n2) { + if (!n1.startsWith("http://xmlpull.org/v1/doc/")) + return false; + if (prop) + return n1.substring(42).equals(n2); + else + return n1.substring(40).equals(n2); + } + + private final boolean adjustNsp() throws XmlPullParserException { + + boolean any = false; + + for (int i = 0; i < attributeCount << 2; i += 4) { + // * 4 - 4; i >= 0; i -= 4) { + + String attrName = attributes[i + 2]; + int cut = attrName.indexOf(':'); + String prefix; + + if (cut != -1) { + prefix = attrName.substring(0, cut); + attrName = attrName.substring(cut + 1); + } + else if (attrName.equals("xmlns")) { + prefix = attrName; + attrName = null; + } + else + continue; + + if (!prefix.equals("xmlns")) { + any = true; + } + else { + int j = (nspCounts[depth]++) << 1; + + nspStack = ensureCapacity(nspStack, j + 2); + nspStack[j] = attrName; + nspStack[j + 1] = attributes[i + 3]; + + if (attrName != null && attributes[i + 3].equals("")) + error("illegal empty namespace"); + + // prefixMap = new PrefixMap (prefixMap, attrName, attr.getValue ()); + + //System.out.println (prefixMap); + + System.arraycopy( + attributes, + i + 4, + attributes, + i, + ((--attributeCount) << 2) - i); + + i -= 4; + } + } + + if (any) { + for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) { + + String attrName = attributes[i + 2]; + int cut = attrName.indexOf(':'); + + if (cut == 0 && !relaxed) + throw new RuntimeException( + "illegal attribute name: " + attrName + " at " + this); + + else if (cut != -1) { + String attrPrefix = attrName.substring(0, cut); + + attrName = attrName.substring(cut + 1); + + String attrNs = getNamespace(attrPrefix); + + if (attrNs == null && !relaxed) + throw new RuntimeException( + "Undefined Prefix: " + attrPrefix + " in " + this); + + attributes[i] = attrNs; + attributes[i + 1] = attrPrefix; + attributes[i + 2] = attrName; + + /* + if (!relaxed) { + for (int j = (attributeCount << 2) - 4; j > i; j -= 4) + if (attrName.equals(attributes[j + 2]) + && attrNs.equals(attributes[j])) + exception( + "Duplicate Attribute: {" + + attrNs + + "}" + + attrName); + } + */ + } + } + } + + int cut = name.indexOf(':'); + + if (cut == 0) + error("illegal tag name: " + name); + + if (cut != -1) { + prefix = name.substring(0, cut); + name = name.substring(cut + 1); + } + + this.namespace = getNamespace(prefix); + + if (this.namespace == null) { + if (prefix != null) + error("undefined prefix: " + prefix); + this.namespace = NO_NAMESPACE; + } + + return any; + } + + private final String[] ensureCapacity(String[] arr, int required) { + if (arr.length >= required) + return arr; + String[] bigger = new String[required + 16]; + System.arraycopy(arr, 0, bigger, 0, arr.length); + return bigger; + } + + private final void error(String desc) throws XmlPullParserException { + if (relaxed) { + if (error == null) + error = "ERR: " + desc; + } + else + exception(desc); + } + + private final void exception(String desc) throws XmlPullParserException { + throw new XmlPullParserException( + desc.length() < 100 ? desc : desc.substring(0, 100) + "\n", + this, + null); + } + + /** + * common base for next and nextToken. Clears the state, except from + * txtPos and whitespace. Does not set the type variable */ + + private final void nextImpl() throws IOException, XmlPullParserException { + + if (reader == null) + exception("No Input specified"); + + if (type == END_TAG) + depth--; + + while (true) { + attributeCount = -1; + + // degenerated needs to be handled before error because of possible + // processor expectations(!) + + if (degenerated) { + degenerated = false; + type = END_TAG; + return; + } + + + if (error != null) { + for (int i = 0; i < error.length(); i++) + push(error.charAt(i)); + // text = error; + error = null; + type = COMMENT; + return; + } + + + if (relaxed + && (stackMismatch > 0 || (peek(0) == -1 && depth > 0))) { + int sp = (depth - 1) << 2; + type = END_TAG; + namespace = elementStack[sp]; + prefix = elementStack[sp + 1]; + name = elementStack[sp + 2]; + if (stackMismatch != 1) + error = "missing end tag /" + name + " inserted"; + if (stackMismatch > 0) + stackMismatch--; + return; + } + + prefix = null; + name = null; + namespace = null; + // text = null; + + type = peekType(); + + switch (type) { + + case ENTITY_REF : + pushEntity(); + return; + + case START_TAG : + parseStartTag(false); + return; + + case END_TAG : + parseEndTag(); + return; + + case END_DOCUMENT : + return; + + case TEXT : + pushText('<', !token); + if (depth == 0) { + if (isWhitespace) + type = IGNORABLE_WHITESPACE; + // make exception switchable for instances.chg... !!!! + // else + // exception ("text '"+getText ()+"' not allowed outside root element"); + } + return; + + default : + type = parseLegacy(token); + if (type != XML_DECL) + return; + } + } + } + + private final int parseLegacy(boolean push) + throws IOException, XmlPullParserException { + + String req = ""; + int term; + int result; + int prev = 0; + + read(); // < + int c = read(); + + if (c == '?') { + if ((peek(0) == 'x' || peek(0) == 'X') + && (peek(1) == 'm' || peek(1) == 'M')) { + + if (push) { + push(peek(0)); + push(peek(1)); + } + read(); + read(); + + if ((peek(0) == 'l' || peek(0) == 'L') && peek(1) <= ' ') { + + if (line != 1 || column > 4) + error("PI must not start with xml"); + + parseStartTag(true); + + if (attributeCount < 1 || !"version".equals(attributes[2])) + error("version expected"); + + version = attributes[3]; + + int pos = 1; + + if (pos < attributeCount + && "encoding".equals(attributes[2 + 4])) { + encoding = attributes[3 + 4]; + pos++; + } + + if (pos < attributeCount + && "standalone".equals(attributes[4 * pos + 2])) { + String st = attributes[3 + 4 * pos]; + if ("yes".equals(st)) + standalone = new Boolean(true); + else if ("no".equals(st)) + standalone = new Boolean(false); + else + error("illegal standalone value: " + st); + pos++; + } + + if (pos != attributeCount) + error("illegal xmldecl"); + + isWhitespace = true; + txtPos = 0; + + return XML_DECL; + } + } + + /* int c0 = read (); + int c1 = read (); + int */ + + term = '?'; + result = PROCESSING_INSTRUCTION; + } + else if (c == '!') { + if (peek(0) == '-') { + result = COMMENT; + req = "--"; + term = '-'; + } + else if (peek(0) == '[') { + result = CDSECT; + req = "[CDATA["; + term = ']'; + push = true; + } + else { + result = DOCDECL; + req = "DOCTYPE"; + term = -1; + } + } + else { + error("illegal: <" + c); + return COMMENT; + } + + for (int i = 0; i < req.length(); i++) + read(req.charAt(i)); + + if (result == DOCDECL) + parseDoctype(push); + else { + while (true) { + c = read(); + if (c == -1){ + error(UNEXPECTED_EOF); + return COMMENT; + } + + if (push) + push(c); + + if ((term == '?' || c == term) + && peek(0) == term + && peek(1) == '>') + break; + + prev = c; + } + + if (term == '-' && prev == '-') + error("illegal comment delimiter: --->"); + + read(); + read(); + + if (push && term != '?') + txtPos--; + + } + return result; + } + + /** precondition: <! consumed */ + + private final void parseDoctype(boolean push) + throws IOException, XmlPullParserException { + + int nesting = 1; + boolean quoted = false; + + // read(); + + while (true) { + int i = read(); + switch (i) { + + case -1 : + error(UNEXPECTED_EOF); + return; + + case '\'' : + quoted = !quoted; + break; + + case '<' : + if (!quoted) + nesting++; + break; + + case '>' : + if (!quoted) { + if ((--nesting) == 0) + return; + } + break; + } + if (push) + push(i); + } + } + + /* precondition: </ consumed */ + + private final void parseEndTag() + throws IOException, XmlPullParserException { + + read(); // '<' + read(); // '/' + name = readName(); + skip(); + read('>'); + + int sp = (depth - 1) << 2; + + if (depth == 0) { + error("element stack empty"); + type = COMMENT; + return; + } + + if (!name.equals(elementStack[sp + 3])) { + error("expected: /" + elementStack[sp + 3] + " read: " + name); + + // become case insensitive in relaxed mode + + int probe = sp; + while (probe >= 0 && !name.toLowerCase().equals(elementStack[probe + 3].toLowerCase())) { + stackMismatch++; + probe -= 4; + } + + if (probe < 0) { + stackMismatch = 0; + // text = "unexpected end tag ignored"; + type = COMMENT; + return; + } + } + + namespace = elementStack[sp]; + prefix = elementStack[sp + 1]; + name = elementStack[sp + 2]; + } + + private final int peekType() throws IOException { + switch (peek(0)) { + case -1 : + return END_DOCUMENT; + case '&' : + return ENTITY_REF; + case '<' : + switch (peek(1)) { + case '/' : + return END_TAG; + case '?' : + case '!' : + return LEGACY; + default : + return START_TAG; + } + default : + return TEXT; + } + } + + private final String get(int pos) { + return new String(txtBuf, pos, txtPos - pos); + } + + /* + private final String pop (int pos) { + String result = new String (txtBuf, pos, txtPos - pos); + txtPos = pos; + return result; + } + */ + + private final void push(int c) { + + isWhitespace &= c <= ' '; + + if (txtPos == txtBuf.length) { + char[] bigger = new char[txtPos * 4 / 3 + 4]; + System.arraycopy(txtBuf, 0, bigger, 0, txtPos); + txtBuf = bigger; + } + + txtBuf[txtPos++] = (char) c; + } + + /** Sets name and attributes */ + + private final void parseStartTag(boolean xmldecl) + throws IOException, XmlPullParserException { + + if (!xmldecl) + read(); + name = readName(); + attributeCount = 0; + + while (true) { + skip(); + + int c = peek(0); + + if (xmldecl) { + if (c == '?') { + read(); + read('>'); + return; + } + } + else { + if (c == '/') { + degenerated = true; + read(); + skip(); + read('>'); + break; + } + + if (c == '>' && !xmldecl) { + read(); + break; + } + } + + if (c == -1) { + error(UNEXPECTED_EOF); + //type = COMMENT; + return; + } + + String attrName = readName(); + + if (attrName.length() == 0) { + error("attr name expected"); + //type = COMMENT; + break; + } + + int i = (attributeCount++) << 2; + + attributes = ensureCapacity(attributes, i + 4); + + attributes[i++] = ""; + attributes[i++] = null; + attributes[i++] = attrName; + + skip(); + + if (peek(0) != '=') { + error("Attr.value missing f. "+attrName); + attributes[i] = "1"; + } + else { + read('='); + skip(); + int delimiter = peek(0); + + if (delimiter != '\'' && delimiter != '"') { + error("attr value delimiter missing!"); + delimiter = ' '; + } + else + read(); + + int p = txtPos; + pushText(delimiter, true); + + attributes[i] = get(p); + txtPos = p; + + if (delimiter != ' ') + read(); // skip endquote + } + } + + int sp = depth++ << 2; + + elementStack = ensureCapacity(elementStack, sp + 4); + elementStack[sp + 3] = name; + + if (depth >= nspCounts.length) { + int[] bigger = new int[depth + 4]; + System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length); + nspCounts = bigger; + } + + nspCounts[depth] = nspCounts[depth - 1]; + + /* + if(!relaxed){ + for (int i = attributeCount - 1; i > 0; i--) { + for (int j = 0; j < i; j++) { + if (getAttributeName(i).equals(getAttributeName(j))) + exception("Duplicate Attribute: " + getAttributeName(i)); + } + } + } + */ + if (processNsp) + adjustNsp(); + else + namespace = ""; + + elementStack[sp] = namespace; + elementStack[sp + 1] = prefix; + elementStack[sp + 2] = name; + } + + /** + * result: isWhitespace; if the setName parameter is set, + * the name of the entity is stored in "name" */ + + private final void pushEntity() + throws IOException, XmlPullParserException { + + push(read()); // & + + + int pos = txtPos; + + while (true) { + int c = read(); + if (c == ';') + break; + if (c < 128 + && (c < '0' || c > '9') + && (c < 'a' || c > 'z') + && (c < 'A' || c > 'Z') + && c != '_' + && c != '-' + && c != '#') { + if(!relaxed){ + error("unterminated entity ref"); + } + //; ends with:"+(char)c); + if (c != -1) + push(c); + return; + } + + push(c); + } + + String code = get(pos); + txtPos = pos - 1; + if (token && type == ENTITY_REF){ + name = code; + } + + if (code.charAt(0) == '#') { + int c = + (code.charAt(1) == 'x' + ? Integer.parseInt(code.substring(2), 16) + : Integer.parseInt(code.substring(1))); + push(c); + return; + } + + String result = (String) entityMap.get(code); + + unresolved = result == null; + + if (unresolved) { + if (!token) + error("unresolved: &" + code + ";"); + } + else { + for (int i = 0; i < result.length(); i++) + push(result.charAt(i)); + } + } + + /** types: + '<': parse to any token (for nextToken ()) + '"': parse to quote + ' ': parse to whitespace or '>' + */ + + private final void pushText(int delimiter, boolean resolveEntities) + throws IOException, XmlPullParserException { + + int next = peek(0); + int cbrCount = 0; + + while (next != -1 && next != delimiter) { // covers eof, '<', '"' + + if (delimiter == ' ') + if (next <= ' ' || next == '>') + break; + + if (next == '&') { + if (!resolveEntities) + break; + + pushEntity(); + } + else if (next == '\n' && type == START_TAG) { + read(); + push(' '); + } + else + push(read()); + + if (next == '>' && cbrCount >= 2 && delimiter != ']') + error("Illegal: ]]>"); + + if (next == ']') + cbrCount++; + else + cbrCount = 0; + + next = peek(0); + } + } + + private final void read(char c) + throws IOException, XmlPullParserException { + int a = read(); + if (a != c) + error("expected: '" + c + "' actual: '" + ((char) a) + "'"); + } + + private final int read() throws IOException { + int result; + + if (peekCount == 0) + result = peek(0); + else { + result = peek[0]; + peek[0] = peek[1]; + } + // else { + // result = peek[0]; + // System.arraycopy (peek, 1, peek, 0, peekCount-1); + // } + peekCount--; + + column++; + + if (result == '\n') { + + line++; + column = 1; + } + + return result; + } + + /** Does never read more than needed */ + + private final int peek(int pos) throws IOException { + + while (pos >= peekCount) { + + int nw; + + if (srcBuf.length <= 1) + nw = reader.read(); + else if (srcPos < srcCount) + nw = srcBuf[srcPos++]; + else { + srcCount = reader.read(srcBuf, 0, srcBuf.length); + if (srcCount <= 0) + nw = -1; + else + nw = srcBuf[0]; + + srcPos = 1; + } + + if (nw == '\r') { + wasCR = true; + peek[peekCount++] = '\n'; + } + else { + if (nw == '\n') { + if (!wasCR) + peek[peekCount++] = '\n'; + } + else + peek[peekCount++] = nw; + + wasCR = false; + } + } + + return peek[pos]; + } + + private final String readName() + throws IOException, XmlPullParserException { + + int pos = txtPos; + int c = peek(0); + if ((c < 'a' || c > 'z') + && (c < 'A' || c > 'Z') + && c != '_' + && c != ':' + && c < 0x0c0 + && !relaxed) + error("name expected"); + + do { + push(read()); + c = peek(0); + } + while ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') + || c == '_' + || c == '-' + || c == ':' + || c == '.' + || c >= 0x0b7); + + String result = get(pos); + txtPos = pos; + return result; + } + + private final void skip() throws IOException { + + while (true) { + int c = peek(0); + if (c > ' ' || c == -1) + break; + read(); + } + } + + // public part starts here... + + public void setInput(Reader reader) throws XmlPullParserException { + this.reader = reader; + + line = 1; + column = 0; + type = START_DOCUMENT; + name = null; + namespace = null; + degenerated = false; + attributeCount = -1; + encoding = null; + version = null; + standalone = null; + + if (reader == null) + return; + + srcPos = 0; + srcCount = 0; + peekCount = 0; + depth = 0; + + entityMap = new Hashtable(); + entityMap.put("amp", "&"); + entityMap.put("apos", "'"); + entityMap.put("gt", ">"); + entityMap.put("lt", "<"); + entityMap.put("quot", "\""); + } + + public void setInput(InputStream is, String _enc) + throws XmlPullParserException { + + srcPos = 0; + srcCount = 0; + String enc = _enc; + + if (is == null) + throw new IllegalArgumentException(); + + try { + + if (enc == null) { + // read four bytes + + int chk = 0; + + while (srcCount < 4) { + int i = is.read(); + if (i == -1) + break; + chk = (chk << 8) | i; + srcBuf[srcCount++] = (char) i; + } + + if (srcCount == 4) { + switch (chk) { + case 0x00000FEFF : + enc = "UTF-32BE"; + srcCount = 0; + break; + + case 0x0FFFE0000 : + enc = "UTF-32LE"; + srcCount = 0; + break; + + case 0x03c : + enc = "UTF-32BE"; + srcBuf[0] = '<'; + srcCount = 1; + break; + + case 0x03c000000 : + enc = "UTF-32LE"; + srcBuf[0] = '<'; + srcCount = 1; + break; + + case 0x0003c003f : + enc = "UTF-16BE"; + srcBuf[0] = '<'; + srcBuf[1] = '?'; + srcCount = 2; + break; + + case 0x03c003f00 : + enc = "UTF-16LE"; + srcBuf[0] = '<'; + srcBuf[1] = '?'; + srcCount = 2; + break; + + case 0x03c3f786d : + while (true) { + int i = is.read(); + if (i == -1) + break; + srcBuf[srcCount++] = (char) i; + if (i == '>') { + String s = new String(srcBuf, 0, srcCount); + int i0 = s.indexOf("encoding"); + if (i0 != -1) { + while (s.charAt(i0) != '"' + && s.charAt(i0) != '\'') + i0++; + char deli = s.charAt(i0++); + int i1 = s.indexOf(deli, i0); + enc = s.substring(i0, i1); + } + break; + } + } + + default : + if ((chk & 0x0ffff0000) == 0x0FEFF0000) { + enc = "UTF-16BE"; + srcBuf[0] = + (char) ((srcBuf[2] << 8) | srcBuf[3]); + srcCount = 1; + } + else if ((chk & 0x0ffff0000) == 0x0fffe0000) { + enc = "UTF-16LE"; + srcBuf[0] = + (char) ((srcBuf[3] << 8) | srcBuf[2]); + srcCount = 1; + } + else if ((chk & 0x0ffffff00) == 0x0EFBBBF00) { + enc = "UTF-8"; + srcBuf[0] = srcBuf[3]; + srcCount = 1; + } + } + } + } + + if (enc == null) + enc = "UTF-8"; + + int sc = srcCount; + setInput(new InputStreamReader(is, enc)); + encoding = _enc; + srcCount = sc; + } + catch (Exception e) { + throw new XmlPullParserException( + "Invalid stream or encoding: " + e.toString(), + this, + e); + } + } + + public boolean getFeature(String feature) { + if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature)) + return processNsp; + else if (isProp(feature, false, "relaxed")) + return relaxed; + else + return false; + } + + public String getInputEncoding() { + return encoding; + } + + public void defineEntityReplacementText(String entity, String value) + throws XmlPullParserException { + if (entityMap == null) + throw new RuntimeException("entity replacement text must be defined after setInput!"); + entityMap.put(entity, value); + } + + public Object getProperty(String property) { + if (isProp(property, true, "xmldecl-version")) + return version; + if (isProp(property, true, "xmldecl-standalone")) + return standalone; + if (isProp(property, true, "location")) + return location != null ? location : reader.toString(); + return null; + } + + public int getNamespaceCount(int depth) { + if (depth > this.depth) + throw new IndexOutOfBoundsException(); + return nspCounts[depth]; + } + + public String getNamespacePrefix(int pos) { + return nspStack[pos << 1]; + } + + public String getNamespaceUri(int pos) { + return nspStack[(pos << 1) + 1]; + } + + public String getNamespace(String prefix) { + + if ("xml".equals(prefix)) + return "http://www.w3.org/XML/1998/namespace"; + if ("xmlns".equals(prefix)) + return "http://www.w3.org/2000/xmlns/"; + + for (int i = (getNamespaceCount(depth) << 1) - 2; i >= 0; i -= 2) { + if (prefix == null) { + if (nspStack[i] == null) + return nspStack[i + 1]; + } + else if (prefix.equals(nspStack[i])) + return nspStack[i + 1]; + } + return null; + } + + public int getDepth() { + return depth; + } + + public String getPositionDescription() { + + StringBuffer buf = + new StringBuffer(type < TYPES.length ? TYPES[type] : "unknown"); + buf.append(' '); + + if (type == START_TAG || type == END_TAG) { + if (degenerated) + buf.append("(empty) "); + buf.append('<'); + if (type == END_TAG) + buf.append('/'); + + if (prefix != null) + buf.append("{" + namespace + "}" + prefix + ":"); + buf.append(name); + + int cnt = attributeCount << 2; + for (int i = 0; i < cnt; i += 4) { + buf.append(' '); + if (attributes[i + 1] != null) + buf.append( + "{" + attributes[i] + "}" + attributes[i + 1] + ":"); + buf.append(attributes[i + 2] + "='" + attributes[i + 3] + "'"); + } + + buf.append('>'); + } + else if (type == IGNORABLE_WHITESPACE); + else if (type != TEXT) + buf.append(getText()); + else if (isWhitespace) + buf.append("(whitespace)"); + else { + String text = getText(); + if (text.length() > 16) + text = text.substring(0, 16) + "..."; + buf.append(text); + } + + buf.append("@"+line + ":" + column); + if(location != null){ + buf.append(" in "); + buf.append(location); + } + else if(reader != null){ + buf.append(" in "); + buf.append(reader.toString()); + } + return buf.toString(); + } + + public int getLineNumber() { + return line; + } + + public int getColumnNumber() { + return column; + } + + public boolean isWhitespace() throws XmlPullParserException { + if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT) + exception(ILLEGAL_TYPE); + return isWhitespace; + } + + public String getText() { + return type < TEXT + || (type == ENTITY_REF && unresolved) ? null : get(0); + } + + public char[] getTextCharacters(int[] poslen) { + if (type >= TEXT) { + if (type == ENTITY_REF) { + poslen[0] = 0; + poslen[1] = name.length(); + return name.toCharArray(); + } + poslen[0] = 0; + poslen[1] = txtPos; + return txtBuf; + } + + poslen[0] = -1; + poslen[1] = -1; + return null; + } + + public String getNamespace() { + return namespace; + } + + public String getName() { + return name; + } + + public String getPrefix() { + return prefix; + } + + public boolean isEmptyElementTag() throws XmlPullParserException { + if (type != START_TAG) + exception(ILLEGAL_TYPE); + return degenerated; + } + + public int getAttributeCount() { + return attributeCount; + } + + public String getAttributeType(int index) { + return "CDATA"; + } + + public boolean isAttributeDefault(int index) { + return false; + } + + public String getAttributeNamespace(int index) { + if (index >= attributeCount) + throw new IndexOutOfBoundsException(); + return attributes[index << 2]; + } + + public String getAttributeName(int index) { + if (index >= attributeCount) + throw new IndexOutOfBoundsException(); + return attributes[(index << 2) + 2]; + } + + public String getAttributePrefix(int index) { + if (index >= attributeCount) + throw new IndexOutOfBoundsException(); + return attributes[(index << 2) + 1]; + } + + public String getAttributeValue(int index) { + if (index >= attributeCount) + throw new IndexOutOfBoundsException(); + return attributes[(index << 2) + 3]; + } + + public String getAttributeValue(String namespace, String name) { + + for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) { + if (attributes[i + 2].equals(name) + && (namespace == null || attributes[i].equals(namespace))) + return attributes[i + 3]; + } + + return null; + } + + public int getEventType() throws XmlPullParserException { + return type; + } + + public int next() throws XmlPullParserException, IOException { + + txtPos = 0; + isWhitespace = true; + int minType = 9999; + token = false; + + do { + nextImpl(); + if (type < minType) + minType = type; + // if (curr <= TEXT) type = curr; + } + while (minType > ENTITY_REF // ignorable + || (minType >= TEXT && peekType() >= TEXT)); + + type = minType; + if (type > TEXT) + type = TEXT; + + return type; + } + + public int nextToken() throws XmlPullParserException, IOException { + + isWhitespace = true; + txtPos = 0; + + token = true; + nextImpl(); + return type; + } + + // + // utility methods to make XML parsing easier ... + + public int nextTag() throws XmlPullParserException, IOException { + + next(); + if (type == TEXT && isWhitespace) + next(); + + if (type != END_TAG && type != START_TAG) + exception("unexpected type"); + + return type; + } + + public void require(int type, String namespace, String name) + throws XmlPullParserException, IOException { + + if (type != this.type + || (namespace != null && !namespace.equals(getNamespace())) + || (name != null && !name.equals(getName()))) + exception( + "expected: " + TYPES[type] + " {" + namespace + "}" + name); + } + + public String nextText() throws XmlPullParserException, IOException { + if (type != START_TAG) + exception("precondition: START_TAG"); + + next(); + + String result; + + if (type == TEXT) { + result = getText(); + next(); + } + else + result = ""; + + if (type != END_TAG) + exception("END_TAG expected"); + + return result; + } + + public void setFeature(String feature, boolean value) + throws XmlPullParserException { + if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature)) + processNsp = value; + else if (isProp(feature, false, "relaxed")) + relaxed = value; + else + exception("unsupported feature: " + feature); + } + + public void setProperty(String property, Object value) + throws XmlPullParserException { + if(isProp(property, true, "location")) + location = value; + else + throw new XmlPullParserException("unsupported property: " + property); + } + + /** + * Skip sub tree that is currently porser positioned on. + * <br>NOTE: parser must be on START_TAG and when funtion returns + * parser will be positioned on corresponding END_TAG. + */ + + // Implementation copied from Alek's mail... + + public void skipSubTree() throws XmlPullParserException, IOException { + require(START_TAG, null, null); + int level = 1; + while (level > 0) { + int eventType = next(); + if (eventType == END_TAG) { + --level; + } + else if (eventType == START_TAG) { + ++level; + } + } + } +} diff --git a/xml/src/main/java/org/kxml2/io/KXmlSerializer.java b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java new file mode 100644 index 0000000..d63ed04 --- /dev/null +++ b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java @@ -0,0 +1,562 @@ +/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ + + +package org.kxml2.io; + +import java.io.*; +import org.xmlpull.v1.*; + +public class KXmlSerializer implements XmlSerializer { + + // static final String UNDEFINED = ":"; + + // BEGIN android-added + /** size (in characters) for the write buffer */ + private static final int WRITE_BUFFER_SIZE = 500; + // END android-added + + // BEGIN android-changed + // (Guarantee that the writer is always buffered.) + private BufferedWriter writer; + // END android-changed + + private boolean pending; + private int auto; + private int depth; + + private String[] elementStack = new String[12]; + //nsp/prefix/name + private int[] nspCounts = new int[4]; + private String[] nspStack = new String[8]; + //prefix/nsp; both empty are "" + private boolean[] indent = new boolean[4]; + private boolean unicode; + private String encoding; + + private final void check(boolean close) throws IOException { + if (!pending) + return; + + depth++; + pending = false; + + if (indent.length <= depth) { + boolean[] hlp = new boolean[depth + 4]; + System.arraycopy(indent, 0, hlp, 0, depth); + indent = hlp; + } + indent[depth] = indent[depth - 1]; + + for (int i = nspCounts[depth - 1]; + i < nspCounts[depth]; + i++) { + writer.write(' '); + writer.write("xmlns"); + if (!"".equals(nspStack[i * 2])) { + writer.write(':'); + writer.write(nspStack[i * 2]); + } + else if ("".equals(getNamespace()) && !"".equals(nspStack[i * 2 + 1])) + throw new IllegalStateException("Cannot set default namespace for elements in no namespace"); + writer.write("=\""); + writeEscaped(nspStack[i * 2 + 1], '"'); + writer.write('"'); + } + + if (nspCounts.length <= depth + 1) { + int[] hlp = new int[depth + 8]; + System.arraycopy(nspCounts, 0, hlp, 0, depth + 1); + nspCounts = hlp; + } + + nspCounts[depth + 1] = nspCounts[depth]; + // nspCounts[depth + 2] = nspCounts[depth]; + + writer.write(close ? " />" : ">"); + } + + private final void writeEscaped(String s, int quot) + throws IOException { + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '\n': + case '\r': + case '\t': + if(quot == -1) + writer.write(c); + else + writer.write("&#"+((int) c)+';'); + break; + case '&' : + writer.write("&"); + break; + case '>' : + writer.write(">"); + break; + case '<' : + writer.write("<"); + break; + case '"' : + case '\'' : + if (c == quot) { + writer.write( + c == '"' ? """ : "'"); + break; + } + default : + //if(c < ' ') + // throw new IllegalArgumentException("Illegal control code:"+((int) c)); + + if (c >= ' ' && c !='@' && (c < 127 || unicode)) + writer.write(c); + else + writer.write("&#" + ((int) c) + ";"); + + } + } + } + + /* + private final void writeIndent() throws IOException { + writer.write("\r\n"); + for (int i = 0; i < depth; i++) + writer.write(' '); + }*/ + + public void docdecl(String dd) throws IOException { + writer.write("<!DOCTYPE"); + writer.write(dd); + writer.write(">"); + } + + public void endDocument() throws IOException { + while (depth > 0) { + endTag( + elementStack[depth * 3 - 3], + elementStack[depth * 3 - 1]); + } + flush(); + } + + public void entityRef(String name) throws IOException { + check(false); + writer.write('&'); + writer.write(name); + writer.write(';'); + } + + public boolean getFeature(String name) { + //return false; + return ( + "http://xmlpull.org/v1/doc/features.html#indent-output" + .equals( + name)) + ? indent[depth] + : false; + } + + public String getPrefix(String namespace, boolean create) { + try { + return getPrefix(namespace, false, create); + } + catch (IOException e) { + throw new RuntimeException(e.toString()); + } + } + + private final String getPrefix( + String namespace, + boolean includeDefault, + boolean create) + throws IOException { + + for (int i = nspCounts[depth + 1] * 2 - 2; + i >= 0; + i -= 2) { + if (nspStack[i + 1].equals(namespace) + && (includeDefault || !nspStack[i].equals(""))) { + String cand = nspStack[i]; + for (int j = i + 2; + j < nspCounts[depth + 1] * 2; + j++) { + if (nspStack[j].equals(cand)) { + cand = null; + break; + } + } + if (cand != null) + return cand; + } + } + + if (!create) + return null; + + String prefix; + + if ("".equals(namespace)) + prefix = ""; + else { + do { + prefix = "n" + (auto++); + for (int i = nspCounts[depth + 1] * 2 - 2; + i >= 0; + i -= 2) { + if (prefix.equals(nspStack[i])) { + prefix = null; + break; + } + } + } + while (prefix == null); + } + + boolean p = pending; + pending = false; + setPrefix(prefix, namespace); + pending = p; + return prefix; + } + + public Object getProperty(String name) { + throw new RuntimeException("Unsupported property"); + } + + public void ignorableWhitespace(String s) + throws IOException { + text(s); + } + + public void setFeature(String name, boolean value) { + if ("http://xmlpull.org/v1/doc/features.html#indent-output" + .equals(name)) { + indent[depth] = value; + } + else + throw new RuntimeException("Unsupported Feature"); + } + + public void setProperty(String name, Object value) { + throw new RuntimeException( + "Unsupported Property:" + value); + } + + public void setPrefix(String prefix, String namespace) + throws IOException { + + check(false); + if (prefix == null) + prefix = ""; + if (namespace == null) + namespace = ""; + + String defined = getPrefix(namespace, true, false); + + // boil out if already defined + + if (prefix.equals(defined)) + return; + + int pos = (nspCounts[depth + 1]++) << 1; + + if (nspStack.length < pos + 1) { + String[] hlp = new String[nspStack.length + 16]; + System.arraycopy(nspStack, 0, hlp, 0, pos); + nspStack = hlp; + } + + nspStack[pos++] = prefix; + nspStack[pos] = namespace; + } + + public void setOutput(Writer writer) { + // BEGIN android-changed + // Guarantee that the writer is always buffered. + if (writer instanceof BufferedWriter) { + this.writer = (BufferedWriter) writer; + } else { + this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE); + } + // END android-changed + + // elementStack = new String[12]; //nsp/prefix/name + //nspCounts = new int[4]; + //nspStack = new String[8]; //prefix/nsp + //indent = new boolean[4]; + + nspCounts[0] = 2; + nspCounts[1] = 2; + nspStack[0] = ""; + nspStack[1] = ""; + nspStack[2] = "xml"; + nspStack[3] = "http://www.w3.org/XML/1998/namespace"; + pending = false; + auto = 0; + depth = 0; + + unicode = false; + } + + public void setOutput(OutputStream os, String encoding) + throws IOException { + if (os == null) + throw new IllegalArgumentException(); + setOutput( + encoding == null + ? new OutputStreamWriter(os) + : new OutputStreamWriter(os, encoding)); + this.encoding = encoding; + if (encoding != null + && encoding.toLowerCase().startsWith("utf")) + unicode = true; + } + + public void startDocument( + String encoding, + Boolean standalone) + throws IOException { + writer.write("<?xml version='1.0' "); + + if (encoding != null) { + this.encoding = encoding; + if (encoding.toLowerCase().startsWith("utf")) + unicode = true; + } + + if (this.encoding != null) { + writer.write("encoding='"); + writer.write(this.encoding); + writer.write("' "); + } + + if (standalone != null) { + writer.write("standalone='"); + writer.write( + standalone.booleanValue() ? "yes" : "no"); + writer.write("' "); + } + writer.write("?>"); + } + + public XmlSerializer startTag(String namespace, String name) + throws IOException { + check(false); + + // if (namespace == null) + // namespace = ""; + + if (indent[depth]) { + writer.write("\r\n"); + for (int i = 0; i < depth; i++) + writer.write(" "); + } + + int esp = depth * 3; + + if (elementStack.length < esp + 3) { + String[] hlp = new String[elementStack.length + 12]; + System.arraycopy(elementStack, 0, hlp, 0, esp); + elementStack = hlp; + } + + String prefix = + namespace == null + ? "" + : getPrefix(namespace, true, true); + + if ("".equals(namespace)) { + for (int i = nspCounts[depth]; + i < nspCounts[depth + 1]; + i++) { + if ("".equals(nspStack[i * 2]) && !"".equals(nspStack[i * 2 + 1])) { + throw new IllegalStateException("Cannot set default namespace for elements in no namespace"); + } + } + } + + elementStack[esp++] = namespace; + elementStack[esp++] = prefix; + elementStack[esp] = name; + + writer.write('<'); + if (!"".equals(prefix)) { + writer.write(prefix); + writer.write(':'); + } + + writer.write(name); + + pending = true; + + return this; + } + + public XmlSerializer attribute( + String namespace, + String name, + String value) + throws IOException { + if (!pending) + throw new IllegalStateException("illegal position for attribute"); + + // int cnt = nspCounts[depth]; + + if (namespace == null) + namespace = ""; + + // depth--; + // pending = false; + + String prefix = + "".equals(namespace) + ? "" + : getPrefix(namespace, false, true); + + // pending = true; + // depth++; + + /* if (cnt != nspCounts[depth]) { + writer.write(' '); + writer.write("xmlns"); + if (nspStack[cnt * 2] != null) { + writer.write(':'); + writer.write(nspStack[cnt * 2]); + } + writer.write("=\""); + writeEscaped(nspStack[cnt * 2 + 1], '"'); + writer.write('"'); + } + */ + + writer.write(' '); + if (!"".equals(prefix)) { + writer.write(prefix); + writer.write(':'); + } + writer.write(name); + writer.write('='); + char q = value.indexOf('"') == -1 ? '"' : '\''; + writer.write(q); + writeEscaped(value, q); + writer.write(q); + + return this; + } + + public void flush() throws IOException { + check(false); + writer.flush(); + } + /* + public void close() throws IOException { + check(); + writer.close(); + } + */ + public XmlSerializer endTag(String namespace, String name) + throws IOException { + + if (!pending) + depth--; + // if (namespace == null) + // namespace = ""; + + if ((namespace == null + && elementStack[depth * 3] != null) + || (namespace != null + && !namespace.equals(elementStack[depth * 3])) + || !elementStack[depth * 3 + 2].equals(name)) + throw new IllegalArgumentException("</{"+namespace+"}"+name+"> does not match start"); + + if (pending) { + check(true); + depth--; + } + else { + if (indent[depth + 1]) { + writer.write("\r\n"); + for (int i = 0; i < depth; i++) + writer.write(" "); + } + + writer.write("</"); + String prefix = elementStack[depth * 3 + 1]; + if (!"".equals(prefix)) { + writer.write(prefix); + writer.write(':'); + } + writer.write(name); + writer.write('>'); + } + + nspCounts[depth + 1] = nspCounts[depth]; + return this; + } + + public String getNamespace() { + return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3]; + } + + public String getName() { + return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1]; + } + + public int getDepth() { + return pending ? depth + 1 : depth; + } + + public XmlSerializer text(String text) throws IOException { + check(false); + indent[depth] = false; + writeEscaped(text, -1); + return this; + } + + public XmlSerializer text(char[] text, int start, int len) + throws IOException { + text(new String(text, start, len)); + return this; + } + + public void cdsect(String data) throws IOException { + check(false); + writer.write("<![CDATA["); + writer.write(data); + writer.write("]]>"); + } + + public void comment(String comment) throws IOException { + check(false); + writer.write("<!--"); + writer.write(comment); + writer.write("-->"); + } + + public void processingInstruction(String pi) + throws IOException { + check(false); + writer.write("<?"); + writer.write(pi); + writer.write("?>"); + } +} diff --git a/xml/src/main/java/org/kxml2/kdom/Document.java b/xml/src/main/java/org/kxml2/kdom/Document.java new file mode 100644 index 0000000..859334c --- /dev/null +++ b/xml/src/main/java/org/kxml2/kdom/Document.java @@ -0,0 +1,129 @@ +/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ + + +package org.kxml2.kdom; + +import java.io.*; + +import org.xmlpull.v1.*; +/** The document consists of some legacy events and a single root + element. This class basically adds some consistency checks to + Node. */ + +public class Document extends Node { + + protected int rootIndex = -1; + String encoding; + Boolean standalone; + + /** returns "#document" */ + + public String getEncoding () { + return encoding; + } + + public void setEncoding(String enc) { + this.encoding = enc; + } + + public void setStandalone (Boolean standalone) { + this.standalone = standalone; + } + + public Boolean getStandalone() { + return standalone; + } + + + public String getName() { + return "#document"; + } + + /** Adds a child at the given index position. Throws + an exception when a second root element is added */ + + public void addChild(int index, int type, Object child) { + if (type == ELEMENT) { + // if (rootIndex != -1) + // throw new RuntimeException("Only one document root element allowed"); + + rootIndex = index; + } + else if (rootIndex >= index) + rootIndex++; + + super.addChild(index, type, child); + } + + /** reads the document and checks if the last event + is END_DOCUMENT. If not, an exception is thrown. + The end event is consumed. For parsing partial + XML structures, consider using Node.parse (). */ + + public void parse(XmlPullParser parser) + throws IOException, XmlPullParserException { + + parser.require(XmlPullParser.START_DOCUMENT, null, null); + parser.nextToken (); + + encoding = parser.getInputEncoding(); + standalone = (Boolean)parser.getProperty ("http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone"); + + super.parse(parser); + + if (parser.getEventType() != XmlPullParser.END_DOCUMENT) + throw new RuntimeException("Document end expected!"); + + } + + public void removeChild(int index) { + if (index == rootIndex) + rootIndex = -1; + else if (index < rootIndex) + rootIndex--; + + super.removeChild(index); + } + + /** returns the root element of this document. */ + + public Element getRootElement() { + if (rootIndex == -1) + throw new RuntimeException("Document has no root element!"); + + return (Element) getChild(rootIndex); + } + + + /** Writes this node to the given XmlWriter. For node and document, + this method is identical to writeChildren, except that the + stream is flushed automatically. */ + + public void write(XmlSerializer writer) + throws IOException { + + writer.startDocument(encoding, standalone); + writeChildren(writer); + writer.endDocument(); + } + + +}
\ No newline at end of file diff --git a/xml/src/main/java/org/kxml2/kdom/Element.java b/xml/src/main/java/org/kxml2/kdom/Element.java new file mode 100644 index 0000000..6a5777b --- /dev/null +++ b/xml/src/main/java/org/kxml2/kdom/Element.java @@ -0,0 +1,335 @@ +/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ + +package org.kxml2.kdom; + +import java.io.*; +import java.util.*; + +import org.xmlpull.v1.*; + +/** + * In order to create an element, please use the createElement method + * instead of invoking the constructor directly. The right place to + * add user defined initialization code is the init method. */ + +public class Element extends Node { + + protected String namespace; + protected String name; + protected Vector attributes; + protected Node parent; + protected Vector prefixes; + + public Element() { + } + + /** + * called when all properties are set, but before children + * are parsed. Please do not use setParent for initialization + * code any longer. */ + + public void init() { + } + + + + + /** + * removes all children and attributes */ + + public void clear() { + attributes = null; + children = null; + } + + /** + * Forwards creation request to parent if any, otherwise + * calls super.createElement. */ + + public Element createElement( + String namespace, + String name) { + + return (this.parent == null) + ? super.createElement(namespace, name) + : this.parent.createElement(namespace, name); + } + + /** + * Returns the number of attributes of this element. */ + + public int getAttributeCount() { + return attributes == null ? 0 : attributes.size(); + } + + public String getAttributeNamespace (int index) { + return ((String []) attributes.elementAt (index)) [0]; + } + +/* public String getAttributePrefix (int index) { + return ((String []) attributes.elementAt (index)) [1]; + }*/ + + public String getAttributeName (int index) { + return ((String []) attributes.elementAt (index)) [1]; + } + + + public String getAttributeValue (int index) { + return ((String []) attributes.elementAt (index)) [2]; + } + + + public String getAttributeValue (String namespace, String name) { + for (int i = 0; i < getAttributeCount (); i++) { + if (name.equals (getAttributeName (i)) + && (namespace == null || namespace.equals (getAttributeNamespace(i)))) { + return getAttributeValue (i); + } + } + return null; + } + + /** + * Returns the root node, determined by ascending to the + * all parents un of the root element. */ + + public Node getRoot() { + + Element current = this; + + while (current.parent != null) { + if (!(current.parent instanceof Element)) return current.parent; + current = (Element) current.parent; + } + + return current; + } + + /** + * returns the (local) name of the element */ + + public String getName() { + return name; + } + + /** + * returns the namespace of the element */ + + public String getNamespace() { + return namespace; + } + + + /** + * returns the namespace for the given prefix */ + + public String getNamespaceUri (String prefix) { + int cnt = getNamespaceCount (); + for (int i = 0; i < cnt; i++) { + if (prefix == getNamespacePrefix (i) || + (prefix != null && prefix.equals (getNamespacePrefix (i)))) + return getNamespaceUri (i); + } + return parent instanceof Element ? ((Element) parent).getNamespaceUri (prefix) : null; + } + + + /** + * returns the number of declared namespaces, NOT including + * parent elements */ + + public int getNamespaceCount () { + return (prefixes == null ? 0 : prefixes.size ()); + } + + + public String getNamespacePrefix (int i) { + return ((String []) prefixes.elementAt (i)) [0]; + } + + public String getNamespaceUri (int i) { + return ((String []) prefixes.elementAt (i)) [1]; + } + + + /** + * Returns the parent node of this element */ + + public Node getParent() { + return parent; + } + + /* + * Returns the parent element if available, null otherwise + + public Element getParentElement() { + return (parent instanceof Element) + ? ((Element) parent) + : null; + } +*/ + + /** + * Builds the child elements from the given Parser. By overwriting + * parse, an element can take complete control over parsing its + * subtree. */ + + public void parse(XmlPullParser parser) + throws IOException, XmlPullParserException { + + for (int i = parser.getNamespaceCount (parser.getDepth () - 1); + i < parser.getNamespaceCount (parser.getDepth ()); i++) { + setPrefix (parser.getNamespacePrefix (i), parser.getNamespaceUri(i)); + } + + + for (int i = 0; i < parser.getAttributeCount (); i++) + setAttribute (parser.getAttributeNamespace (i), +// parser.getAttributePrefix (i), + parser.getAttributeName (i), + parser.getAttributeValue (i)); + + + // if (prefixMap == null) throw new RuntimeException ("!!"); + + init(); + + + if (parser.isEmptyElementTag()) + parser.nextToken (); + else { + parser.nextToken (); + super.parse(parser); + + if (getChildCount() == 0) + addChild(IGNORABLE_WHITESPACE, ""); + } + + parser.require( + XmlPullParser.END_TAG, + getNamespace(), + getName()); + + parser.nextToken (); + } + + + /** + * Sets the given attribute; a value of null removes the attribute */ + + public void setAttribute (String namespace, String name, String value) { + if (attributes == null) + attributes = new Vector (); + + if (namespace == null) + namespace = ""; + + for (int i = attributes.size()-1; i >=0; i--){ + String[] attribut = (String[]) attributes.elementAt(i); + if (attribut[0].equals(namespace) && + attribut[1].equals(name)){ + + if (value == null) { + attributes.removeElementAt(i); + } + else { + attribut[2] = value; + } + return; + } + } + + attributes.addElement + (new String [] {namespace, name, value}); + } + + + /** + * Sets the given prefix; a namespace value of null removess the + * prefix */ + + public void setPrefix (String prefix, String namespace) { + if (prefixes == null) prefixes = new Vector (); + prefixes.addElement (new String [] {prefix, namespace}); + } + + + /** + * sets the name of the element */ + + public void setName(String name) { + this.name = name; + } + + /** + * sets the namespace of the element. Please note: For no + * namespace, please use Xml.NO_NAMESPACE, null is not a legal + * value. Currently, null is converted to Xml.NO_NAMESPACE, but + * future versions may throw an exception. */ + + public void setNamespace(String namespace) { + if (namespace == null) + throw new NullPointerException ("Use \"\" for empty namespace"); + this.namespace = namespace; + } + + /** + * Sets the Parent of this element. Automatically called from the + * add method. Please use with care, you can simply + * create inconsitencies in the document tree structure using + * this method! */ + + protected void setParent(Node parent) { + this.parent = parent; + } + + + /** + * Writes this element and all children to the given XmlWriter. */ + + public void write(XmlSerializer writer) + throws IOException { + + if (prefixes != null) { + for (int i = 0; i < prefixes.size(); i++) { + writer.setPrefix (getNamespacePrefix (i), getNamespaceUri (i)); + } + } + + writer.startTag( + getNamespace(), + getName()); + + int len = getAttributeCount(); + + for (int i = 0; i < len; i++) { + writer.attribute( + getAttributeNamespace(i), + getAttributeName(i), + getAttributeValue(i)); + } + + writeChildren(writer); + + writer.endTag(getNamespace (), getName ()); + } +} diff --git a/xml/src/main/java/org/kxml2/kdom/Node.java b/xml/src/main/java/org/kxml2/kdom/Node.java new file mode 100644 index 0000000..a3cc78d --- /dev/null +++ b/xml/src/main/java/org/kxml2/kdom/Node.java @@ -0,0 +1,366 @@ +/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ + +package org.kxml2.kdom; + +import java.util.*; +import java.io.*; +import org.xmlpull.v1.*; +/** A common base class for Document and Element, also used for + storing XML fragments. */ + +public class Node { //implements XmlIO{ + + public static final int DOCUMENT = 0; + public static final int ELEMENT = 2; + public static final int TEXT = 4; + public static final int CDSECT = 5; + public static final int ENTITY_REF = 6; + public static final int IGNORABLE_WHITESPACE = 7; + public static final int PROCESSING_INSTRUCTION = 8; + public static final int COMMENT = 9; + public static final int DOCDECL = 10; + + protected Vector children; + protected StringBuffer types; + + /** inserts the given child object of the given type at the + given index. */ + + public void addChild(int index, int type, Object child) { + + if (child == null) + throw new NullPointerException(); + + if (children == null) { + children = new Vector(); + types = new StringBuffer(); + } + + if (type == ELEMENT) { + if (!(child instanceof Element)) + throw new RuntimeException("Element obj expected)"); + + ((Element) child).setParent(this); + } + else if (!(child instanceof String)) + throw new RuntimeException("String expected"); + + children.insertElementAt(child, index); + types.insert(index, (char) type); + } + + /** convenience method for addChild (getChildCount (), child) */ + + public void addChild(int type, Object child) { + addChild(getChildCount(), type, child); + } + + /** Builds a default element with the given properties. Elements + should always be created using this method instead of the + constructor in order to enable construction of specialized + subclasses by deriving custom Document classes. Please note: + For no namespace, please use Xml.NO_NAMESPACE, null is not a + legal value. Currently, null is converted to Xml.NO_NAMESPACE, + but future versions may throw an exception. */ + + public Element createElement(String namespace, String name) { + + Element e = new Element(); + e.namespace = namespace == null ? "" : namespace; + e.name = name; + return e; + } + + /** Returns the child object at the given index. For child + elements, an Element object is returned. For all other child + types, a String is returned. */ + + public Object getChild(int index) { + return children.elementAt(index); + } + + /** Returns the number of child objects */ + + public int getChildCount() { + return children == null ? 0 : children.size(); + } + + /** returns the element at the given index. If the node at the + given index is a text node, null is returned */ + + public Element getElement(int index) { + Object child = getChild(index); + return (child instanceof Element) ? (Element) child : null; + } + + /** Returns the element with the given namespace and name. If the + element is not found, or more than one matching elements are + found, an exception is thrown. */ + + public Element getElement(String namespace, String name) { + + int i = indexOf(namespace, name, 0); + int j = indexOf(namespace, name, i + 1); + + if (i == -1 || j != -1) + throw new RuntimeException( + "Element {" + + namespace + + "}" + + name + + (i == -1 ? " not found in " : " more than once in ") + + this); + + return getElement(i); + } + + /* returns "#document-fragment". For elements, the element name is returned + + public String getName() { + return "#document-fragment"; + } + + /** Returns the namespace of the current element. For Node + and Document, Xml.NO_NAMESPACE is returned. + + public String getNamespace() { + return ""; + } + + public int getNamespaceCount () { + return 0; + } + + /** returns the text content if the element has text-only + content. Throws an exception for mixed content + + public String getText() { + + StringBuffer buf = new StringBuffer(); + int len = getChildCount(); + + for (int i = 0; i < len; i++) { + if (isText(i)) + buf.append(getText(i)); + else if (getType(i) == ELEMENT) + throw new RuntimeException("not text-only content!"); + } + + return buf.toString(); + } + */ + + /** Returns the text node with the given index or null if the node + with the given index is not a text node. */ + + public String getText(int index) { + return (isText(index)) ? (String) getChild(index) : null; + } + + /** Returns the type of the child at the given index. Possible + types are ELEMENT, TEXT, COMMENT, and PROCESSING_INSTRUCTION */ + + public int getType(int index) { + return types.charAt(index); + } + + /** Convenience method for indexOf (getNamespace (), name, + startIndex). + + public int indexOf(String name, int startIndex) { + return indexOf(getNamespace(), name, startIndex); + } + */ + + /** Performs search for an element with the given namespace and + name, starting at the given start index. A null namespace + matches any namespace, please use Xml.NO_NAMESPACE for no + namespace). returns -1 if no matching element was found. */ + + public int indexOf(String namespace, String name, int startIndex) { + + int len = getChildCount(); + + for (int i = startIndex; i < len; i++) { + + Element child = getElement(i); + + if (child != null + && name.equals(child.getName()) + && (namespace == null || namespace.equals(child.getNamespace()))) + return i; + } + return -1; + } + + public boolean isText(int i) { + int t = getType(i); + return t == TEXT || t == IGNORABLE_WHITESPACE || t == CDSECT; + } + + /** Recursively builds the child elements from the given parser + until an end tag or end document is found. + The end tag is not consumed. */ + + public void parse(XmlPullParser parser) + throws IOException, XmlPullParserException { + + boolean leave = false; + + do { + int type = parser.getEventType(); + + // System.out.println(parser.getPositionDescription()); + + switch (type) { + + case XmlPullParser.START_TAG : + { + Element child = + createElement( + parser.getNamespace(), + parser.getName()); + // child.setAttributes (event.getAttributes ()); + addChild(ELEMENT, child); + + // order is important here since + // setparent may perform some init code! + + child.parse(parser); + break; + } + + case XmlPullParser.END_DOCUMENT : + case XmlPullParser.END_TAG : + leave = true; + break; + + default : + if (parser.getText() != null) + addChild( + type == XmlPullParser.ENTITY_REF ? TEXT : type, + parser.getText()); + else if ( + type == XmlPullParser.ENTITY_REF + && parser.getName() != null) { + addChild(ENTITY_REF, parser.getName()); + } + parser.nextToken(); + } + } + while (!leave); + } + + /** Removes the child object at the given index */ + + public void removeChild(int idx) { + children.removeElementAt(idx); + + /*** Modification by HHS - start ***/ + // types.deleteCharAt (index); + /***/ + int n = types.length() - 1; + + for (int i = idx; i < n; i++) + types.setCharAt(i, types.charAt(i + 1)); + + types.setLength(n); + + /*** Modification by HHS - end ***/ + } + + /* returns a valid XML representation of this Element including + attributes and children. + public String toString() { + try { + ByteArrayOutputStream bos = + new ByteArrayOutputStream(); + XmlWriter xw = + new XmlWriter(new OutputStreamWriter(bos)); + write(xw); + xw.close(); + return new String(bos.toByteArray()); + } + catch (IOException e) { + throw new RuntimeException(e.toString()); + } + } + */ + + /** Writes this node to the given XmlWriter. For node and document, + this method is identical to writeChildren, except that the + stream is flushed automatically. */ + + public void write(XmlSerializer writer) throws IOException { + writeChildren(writer); + writer.flush(); + } + + /** Writes the children of this node to the given XmlWriter. */ + + public void writeChildren(XmlSerializer writer) throws IOException { + if (children == null) + return; + + int len = children.size(); + + for (int i = 0; i < len; i++) { + int type = getType(i); + Object child = children.elementAt(i); + switch (type) { + case ELEMENT : + ((Element) child).write(writer); + break; + + case TEXT : + writer.text((String) child); + break; + + case IGNORABLE_WHITESPACE : + writer.ignorableWhitespace((String) child); + break; + + case CDSECT : + writer.cdsect((String) child); + break; + + case COMMENT : + writer.comment((String) child); + break; + + case ENTITY_REF : + writer.entityRef((String) child); + break; + + case PROCESSING_INSTRUCTION : + writer.processingInstruction((String) child); + break; + + case DOCDECL : + writer.docdecl((String) child); + break; + + default : + throw new RuntimeException("Illegal type: " + type); + } + } + } +} diff --git a/xml/src/main/java/org/kxml2/wap/Wbxml.java b/xml/src/main/java/org/kxml2/wap/Wbxml.java new file mode 100644 index 0000000..5b0c2d3 --- /dev/null +++ b/xml/src/main/java/org/kxml2/wap/Wbxml.java @@ -0,0 +1,49 @@ +/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ + +package org.kxml2.wap; + + +/** contains the WBXML constants */ + + +public interface Wbxml { + + static public final int SWITCH_PAGE = 0; + static public final int END = 1; + static public final int ENTITY = 2; + static public final int STR_I = 3; + static public final int LITERAL = 4; + static public final int EXT_I_0 = 0x40; + static public final int EXT_I_1 = 0x41; + static public final int EXT_I_2 = 0x42; + static public final int PI = 0x43; + static public final int LITERAL_C = 0x44; + static public final int EXT_T_0 = 0x80; + static public final int EXT_T_1 = 0x81; + static public final int EXT_T_2 = 0x82; + static public final int STR_T = 0x83; + static public final int LITERAL_A = 0x084; + static public final int EXT_0 = 0x0c0; + static public final int EXT_1 = 0x0c1; + static public final int EXT_2 = 0x0c2; + static public final int OPAQUE = 0x0c3; + static public final int LITERAL_AC = 0x0c4; +} diff --git a/xml/src/main/java/org/kxml2/wap/WbxmlParser.java b/xml/src/main/java/org/kxml2/wap/WbxmlParser.java new file mode 100644 index 0000000..617e1d4 --- /dev/null +++ b/xml/src/main/java/org/kxml2/wap/WbxmlParser.java @@ -0,0 +1,1075 @@ +/* Copyright (c) 2002,2003,2004 Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ + +// Contributors: Bjorn Aadland, Chris Bartley, Nicola Fankhauser, +// Victor Havin, Christian Kurzke, Bogdan Onoiu, +// Elias Ross, Jain Sanjay, David Santoro. + +package org.kxml2.wap; + +import java.io.*; +import java.util.Vector; +import java.util.Hashtable; + +import org.xmlpull.v1.*; + + +public class WbxmlParser implements XmlPullParser { + + static final String HEX_DIGITS = "0123456789abcdef"; + + /** Parser event type for Wbxml-specific events. The Wbxml event code can be + * accessed with getWapCode() */ + + public static final int WAP_EXTENSION = 64; + + static final private String UNEXPECTED_EOF = + "Unexpected EOF"; + static final private String ILLEGAL_TYPE = + "Wrong event type"; + + private InputStream in; + + private int TAG_TABLE = 0; + private int ATTR_START_TABLE = 1; + private int ATTR_VALUE_TABLE = 2; + + private String[] attrStartTable; + private String[] attrValueTable; + private String[] tagTable; + private byte[] stringTable; + private Hashtable cacheStringTable = null; + private boolean processNsp; + + private int depth; + private String[] elementStack = new String[16]; + private String[] nspStack = new String[8]; + private int[] nspCounts = new int[4]; + + private int attributeCount; + private String[] attributes = new String[16]; + private int nextId = -2; + + private Vector tables = new Vector(); + + private int version; + private int publicIdentifierId; + + // StartTag current; + // ParseEvent next; + + private String prefix; + private String namespace; + private String name; + private String text; + + private Object wapExtensionData; + private int wapCode; + + private int type; + + private boolean degenerated; + private boolean isWhitespace; + private String encoding; + + public boolean getFeature(String feature) { + if (XmlPullParser + .FEATURE_PROCESS_NAMESPACES + .equals(feature)) + return processNsp; + else + return false; + } + + public String getInputEncoding() { + return encoding; + } + + public void defineEntityReplacementText( + String entity, + String value) + throws XmlPullParserException { + + // just ignore, has no effect + } + + public Object getProperty(String property) { + return null; + } + + public int getNamespaceCount(int depth) { + if (depth > this.depth) + throw new IndexOutOfBoundsException(); + return nspCounts[depth]; + } + + public String getNamespacePrefix(int pos) { + return nspStack[pos << 1]; + } + + public String getNamespaceUri(int pos) { + return nspStack[(pos << 1) + 1]; + } + + public String getNamespace(String prefix) { + + if ("xml".equals(prefix)) + return "http://www.w3.org/XML/1998/namespace"; + if ("xmlns".equals(prefix)) + return "http://www.w3.org/2000/xmlns/"; + + for (int i = (getNamespaceCount(depth) << 1) - 2; + i >= 0; + i -= 2) { + if (prefix == null) { + if (nspStack[i] == null) + return nspStack[i + 1]; + } + else if (prefix.equals(nspStack[i])) + return nspStack[i + 1]; + } + return null; + } + + public int getDepth() { + return depth; + } + + public String getPositionDescription() { + + StringBuffer buf = + new StringBuffer( + type < TYPES.length ? TYPES[type] : "unknown"); + buf.append(' '); + + if (type == START_TAG || type == END_TAG) { + if (degenerated) + buf.append("(empty) "); + buf.append('<'); + if (type == END_TAG) + buf.append('/'); + + if (prefix != null) + buf.append("{" + namespace + "}" + prefix + ":"); + buf.append(name); + + int cnt = attributeCount << 2; + for (int i = 0; i < cnt; i += 4) { + buf.append(' '); + if (attributes[i + 1] != null) + buf.append( + "{" + + attributes[i] + + "}" + + attributes[i + + 1] + + ":"); + buf.append( + attributes[i + + 2] + + "='" + + attributes[i + + 3] + + "'"); + } + + buf.append('>'); + } + else if (type == IGNORABLE_WHITESPACE); + else if (type != TEXT) + buf.append(getText()); + else if (isWhitespace) + buf.append("(whitespace)"); + else { + String text = getText(); + if (text.length() > 16) + text = text.substring(0, 16) + "..."; + buf.append(text); + } + + return buf.toString(); + } + + public int getLineNumber() { + return -1; + } + + public int getColumnNumber() { + return -1; + } + + public boolean isWhitespace() + throws XmlPullParserException { + if (type != TEXT + && type != IGNORABLE_WHITESPACE + && type != CDSECT) + exception(ILLEGAL_TYPE); + return isWhitespace; + } + + public String getText() { + return text; + } + + public char[] getTextCharacters(int[] poslen) { + if (type >= TEXT) { + poslen[0] = 0; + poslen[1] = text.length(); + char[] buf = new char[text.length()]; + text.getChars(0, text.length(), buf, 0); + return buf; + } + + poslen[0] = -1; + poslen[1] = -1; + return null; + } + + public String getNamespace() { + return namespace; + } + + public String getName() { + return name; + } + + public String getPrefix() { + return prefix; + } + + public boolean isEmptyElementTag() + throws XmlPullParserException { + if (type != START_TAG) + exception(ILLEGAL_TYPE); + return degenerated; + } + + public int getAttributeCount() { + return attributeCount; + } + + public String getAttributeType(int index) { + return "CDATA"; + } + + public boolean isAttributeDefault(int index) { + return false; + } + + public String getAttributeNamespace(int index) { + if (index >= attributeCount) + throw new IndexOutOfBoundsException(); + return attributes[index << 2]; + } + + public String getAttributeName(int index) { + if (index >= attributeCount) + throw new IndexOutOfBoundsException(); + return attributes[(index << 2) + 2]; + } + + public String getAttributePrefix(int index) { + if (index >= attributeCount) + throw new IndexOutOfBoundsException(); + return attributes[(index << 2) + 1]; + } + + public String getAttributeValue(int index) { + if (index >= attributeCount) + throw new IndexOutOfBoundsException(); + return attributes[(index << 2) + 3]; + } + + public String getAttributeValue( + String namespace, + String name) { + + for (int i = (attributeCount << 2) - 4; + i >= 0; + i -= 4) { + if (attributes[i + 2].equals(name) + && (namespace == null + || attributes[i].equals(namespace))) + return attributes[i + 3]; + } + + return null; + } + + public int getEventType() throws XmlPullParserException { + return type; + } + + + // TODO: Reuse resolveWapExtension here? Raw Wap extensions would still be accessible + // via nextToken(); ....? + + public int next() throws XmlPullParserException, IOException { + + isWhitespace = true; + int minType = 9999; + + while (true) { + + String save = text; + + nextImpl(); + + if (type < minType) + minType = type; + + if (minType > CDSECT) continue; // no "real" event so far + + if (minType >= TEXT) { // text, see if accumulate + + if (save != null) text = text == null ? save : save + text; + + switch(peekId()) { + case Wbxml.ENTITY: + case Wbxml.STR_I: + case Wbxml.STR_T: + case Wbxml.LITERAL: + case Wbxml.LITERAL_C: + case Wbxml.LITERAL_A: + case Wbxml.LITERAL_AC: continue; + } + } + + break; + } + + type = minType; + + if (type > TEXT) + type = TEXT; + + return type; + } + + + public int nextToken() throws XmlPullParserException, IOException { + + isWhitespace = true; + nextImpl(); + return type; + } + + + + public int nextTag() throws XmlPullParserException, IOException { + + next(); + if (type == TEXT && isWhitespace) + next(); + + if (type != END_TAG && type != START_TAG) + exception("unexpected type"); + + return type; + } + + + public String nextText() throws XmlPullParserException, IOException { + if (type != START_TAG) + exception("precondition: START_TAG"); + + next(); + + String result; + + if (type == TEXT) { + result = getText(); + next(); + } + else + result = ""; + + if (type != END_TAG) + exception("END_TAG expected"); + + return result; + } + + + public void require(int type, String namespace, String name) + throws XmlPullParserException, IOException { + + if (type != this.type + || (namespace != null && !namespace.equals(getNamespace())) + || (name != null && !name.equals(getName()))) + exception( + "expected: " + (type == WAP_EXTENSION ? "WAP Ext." : (TYPES[type] + " {" + namespace + "}" + name))); + } + + + public void setInput(Reader reader) throws XmlPullParserException { + exception("InputStream required"); + } + + public void setInput(InputStream in, String enc) + throws XmlPullParserException { + + this.in = in; + + try { + version = readByte(); + publicIdentifierId = readInt(); + + if (publicIdentifierId == 0) + readInt(); + + int charset = readInt(); // skip charset + + if (null == enc){ + switch (charset){ + case 4: encoding = "ISO-8859-1"; break; + case 106: encoding = "UTF-8"; break; + // add more if you need them + // http://www.iana.org/assignments/character-sets + // case MIBenum: encoding = Name break; + default: throw new UnsupportedEncodingException(""+charset); + } + }else{ + encoding = enc; + } + + int strTabSize = readInt(); + stringTable = new byte[strTabSize]; + + int ok = 0; + while(ok < strTabSize){ + int cnt = in.read(stringTable, ok, strTabSize - ok); + if(cnt <= 0) break; + ok += cnt; + } + + selectPage(0, true); + selectPage(0, false); + } + catch (IOException e) { + exception("Illegal input format"); + } + } + + public void setFeature(String feature, boolean value) + throws XmlPullParserException { + if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature)) + processNsp = value; + else + exception("unsupported feature: " + feature); + } + + public void setProperty(String property, Object value) + throws XmlPullParserException { + throw new XmlPullParserException("unsupported property: " + property); + } + + // ---------------------- private / internal methods + + private final boolean adjustNsp() + throws XmlPullParserException { + + boolean any = false; + + for (int i = 0; i < attributeCount << 2; i += 4) { + // * 4 - 4; i >= 0; i -= 4) { + + String attrName = attributes[i + 2]; + int cut = attrName.indexOf(':'); + String prefix; + + if (cut != -1) { + prefix = attrName.substring(0, cut); + attrName = attrName.substring(cut + 1); + } + else if (attrName.equals("xmlns")) { + prefix = attrName; + attrName = null; + } + else + continue; + + if (!prefix.equals("xmlns")) { + any = true; + } + else { + int j = (nspCounts[depth]++) << 1; + + nspStack = ensureCapacity(nspStack, j + 2); + nspStack[j] = attrName; + nspStack[j + 1] = attributes[i + 3]; + + if (attrName != null + && attributes[i + 3].equals("")) + exception("illegal empty namespace"); + + // prefixMap = new PrefixMap (prefixMap, attrName, attr.getValue ()); + + //System.out.println (prefixMap); + + System.arraycopy( + attributes, + i + 4, + attributes, + i, + ((--attributeCount) << 2) - i); + + i -= 4; + } + } + + if (any) { + for (int i = (attributeCount << 2) - 4; + i >= 0; + i -= 4) { + + String attrName = attributes[i + 2]; + int cut = attrName.indexOf(':'); + + if (cut == 0) + throw new RuntimeException( + "illegal attribute name: " + + attrName + + " at " + + this); + + else if (cut != -1) { + String attrPrefix = + attrName.substring(0, cut); + + attrName = attrName.substring(cut + 1); + + String attrNs = getNamespace(attrPrefix); + + if (attrNs == null) + throw new RuntimeException( + "Undefined Prefix: " + + attrPrefix + + " in " + + this); + + attributes[i] = attrNs; + attributes[i + 1] = attrPrefix; + attributes[i + 2] = attrName; + + for (int j = (attributeCount << 2) - 4; + j > i; + j -= 4) + if (attrName.equals(attributes[j + 2]) + && attrNs.equals(attributes[j])) + exception( + "Duplicate Attribute: {" + + attrNs + + "}" + + attrName); + } + } + } + + int cut = name.indexOf(':'); + + if (cut == 0) + exception("illegal tag name: " + name); + else if (cut != -1) { + prefix = name.substring(0, cut); + name = name.substring(cut + 1); + } + + this.namespace = getNamespace(prefix); + + if (this.namespace == null) { + if (prefix != null) + exception("undefined prefix: " + prefix); + this.namespace = NO_NAMESPACE; + } + + return any; + } + + private final void setTable(int page, int type, String[] table) { + if(stringTable != null){ + throw new RuntimeException("setXxxTable must be called before setInput!"); + } + while(tables.size() < 3*page +3){ + tables.addElement(null); + } + tables.setElementAt(table, page*3+type); + } + + + + + + private final void exception(String desc) + throws XmlPullParserException { + throw new XmlPullParserException(desc, this, null); + } + + + private void selectPage(int nr, boolean tags) throws XmlPullParserException{ + if(tables.size() == 0 && nr == 0) return; + + if(nr*3 > tables.size()) + exception("Code Page "+nr+" undefined!"); + + if(tags) + tagTable = (String[]) tables.elementAt(nr * 3 + TAG_TABLE); + else { + attrStartTable = (String[]) tables.elementAt(nr * 3 + ATTR_START_TABLE); + attrValueTable = (String[]) tables.elementAt(nr * 3 + ATTR_VALUE_TABLE); + } + } + + private final void nextImpl() + throws IOException, XmlPullParserException { + + String s; + + if (type == END_TAG) { + depth--; + } + + if (degenerated) { + type = XmlPullParser.END_TAG; + degenerated = false; + return; + } + + text = null; + prefix = null; + name = null; + + int id = peekId (); + while(id == Wbxml.SWITCH_PAGE){ + nextId = -2; + selectPage(readByte(), true); + id = peekId(); + } + nextId = -2; + + switch (id) { + case -1 : + type = XmlPullParser.END_DOCUMENT; + break; + + case Wbxml.END : + { + int sp = (depth - 1) << 2; + + type = END_TAG; + namespace = elementStack[sp]; + prefix = elementStack[sp + 1]; + name = elementStack[sp + 2]; + } + break; + + case Wbxml.ENTITY : + { + type = ENTITY_REF; + char c = (char) readInt(); + text = "" + c; + name = "#" + ((int) c); + } + + break; + + case Wbxml.STR_I : + type = TEXT; + text = readStrI(); + break; + + case Wbxml.EXT_I_0 : + case Wbxml.EXT_I_1 : + case Wbxml.EXT_I_2 : + case Wbxml.EXT_T_0 : + case Wbxml.EXT_T_1 : + case Wbxml.EXT_T_2 : + case Wbxml.EXT_0 : + case Wbxml.EXT_1 : + case Wbxml.EXT_2 : + case Wbxml.OPAQUE : + + type = WAP_EXTENSION; + wapCode = id; + wapExtensionData = parseWapExtension(id); + break; + + case Wbxml.PI : + throw new RuntimeException("PI curr. not supp."); + // readPI; + // break; + + case Wbxml.STR_T : + { + type = TEXT; + text = readStrT(); + } + break; + + default : + parseElement(id); + } + // } + // while (next == null); + + // return next; + } + + /** Overwrite this method to intercept all wap events */ + + public Object parseWapExtension(int id) throws IOException, XmlPullParserException { + + switch (id) { + case Wbxml.EXT_I_0 : + case Wbxml.EXT_I_1 : + case Wbxml.EXT_I_2 : + return readStrI(); + + case Wbxml.EXT_T_0 : + case Wbxml.EXT_T_1 : + case Wbxml.EXT_T_2 : + return new Integer(readInt()); + + case Wbxml.EXT_0 : + case Wbxml.EXT_1 : + case Wbxml.EXT_2 : + return null; + + case Wbxml.OPAQUE : + { + int count = readInt(); + byte[] buf = new byte[count]; + + while(count > 0){ + count -= in.read(buf, buf.length-count, count); + } + + return buf; + } // case OPAQUE + + + default: + exception("illegal id: "+id); + return null; // dead code + } // SWITCH + } + + public void readAttr() throws IOException, XmlPullParserException { + + int id = readByte(); + int i = 0; + + while (id != 1) { + + while(id == Wbxml.SWITCH_PAGE){ + selectPage(readByte(), false); + id = readByte(); + } + + String name = resolveId(attrStartTable, id); + StringBuffer value; + + int cut = name.indexOf('='); + + if (cut == -1) + value = new StringBuffer(); + else { + value = + new StringBuffer(name.substring(cut + 1)); + name = name.substring(0, cut); + } + + id = readByte(); + while (id > 128 + || id == Wbxml.SWITCH_PAGE + || id == Wbxml.ENTITY + || id == Wbxml.STR_I + || id == Wbxml.STR_T + || (id >= Wbxml.EXT_I_0 && id <= Wbxml.EXT_I_2) + || (id >= Wbxml.EXT_T_0 && id <= Wbxml.EXT_T_2)) { + + switch (id) { + case Wbxml.SWITCH_PAGE : + selectPage(readByte(), false); + break; + + case Wbxml.ENTITY : + value.append((char) readInt()); + break; + + case Wbxml.STR_I : + value.append(readStrI()); + break; + + case Wbxml.EXT_I_0 : + case Wbxml.EXT_I_1 : + case Wbxml.EXT_I_2 : + case Wbxml.EXT_T_0 : + case Wbxml.EXT_T_1 : + case Wbxml.EXT_T_2 : + case Wbxml.EXT_0 : + case Wbxml.EXT_1 : + case Wbxml.EXT_2 : + case Wbxml.OPAQUE : + value.append(resolveWapExtension(id, parseWapExtension(id))); + break; + + case Wbxml.STR_T : + value.append(readStrT()); + break; + + default : + value.append( + resolveId(attrValueTable, id)); + } + + id = readByte(); + } + + attributes = ensureCapacity(attributes, i + 4); + + attributes[i++] = ""; + attributes[i++] = null; + attributes[i++] = name; + attributes[i++] = value.toString(); + + attributeCount++; + } + } + + private int peekId () throws IOException { + if (nextId == -2) { + nextId = in.read (); + } + return nextId; + } + + /** overwrite for own WAP extension handling in attributes and high level parsing + * (above nextToken() level) */ + + protected String resolveWapExtension(int id, Object data){ + + if(data instanceof byte[]){ + StringBuffer sb = new StringBuffer(); + byte[] b = (byte[]) data; + + for (int i = 0; i < b.length; i++) { + sb.append(HEX_DIGITS.charAt((b[i] >> 4) & 0x0f)); + sb.append(HEX_DIGITS.charAt(b[i] & 0x0f)); + } + return sb.toString(); + } + + return "$("+data+")"; + } + + String resolveId(String[] tab, int id) throws IOException { + int idx = (id & 0x07f) - 5; + if (idx == -1){ + wapCode = -1; + return readStrT(); + } + if (idx < 0 + || tab == null + || idx >= tab.length + || tab[idx] == null) + throw new IOException("id " + id + " undef."); + + wapCode = idx+5; + + return tab[idx]; + } + + void parseElement(int id) + throws IOException, XmlPullParserException { + + type = START_TAG; + name = resolveId(tagTable, id & 0x03f); + + attributeCount = 0; + if ((id & 128) != 0) { + readAttr(); + } + + degenerated = (id & 64) == 0; + + int sp = depth++ << 2; + + // transfer to element stack + + elementStack = ensureCapacity(elementStack, sp + 4); + elementStack[sp + 3] = name; + + if (depth >= nspCounts.length) { + int[] bigger = new int[depth + 4]; + System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length); + nspCounts = bigger; + } + + nspCounts[depth] = nspCounts[depth - 1]; + + for (int i = attributeCount - 1; i > 0; i--) { + for (int j = 0; j < i; j++) { + if (getAttributeName(i) + .equals(getAttributeName(j))) + exception( + "Duplicate Attribute: " + + getAttributeName(i)); + } + } + + if (processNsp) + adjustNsp(); + else + namespace = ""; + + elementStack[sp] = namespace; + elementStack[sp + 1] = prefix; + elementStack[sp + 2] = name; + + } + + private final String[] ensureCapacity( + String[] arr, + int required) { + if (arr.length >= required) + return arr; + String[] bigger = new String[required + 16]; + System.arraycopy(arr, 0, bigger, 0, arr.length); + return bigger; + } + + int readByte() throws IOException { + int i = in.read(); + if (i == -1) + throw new IOException("Unexpected EOF"); + return i; + } + + int readInt() throws IOException { + int result = 0; + int i; + + do { + i = readByte(); + result = (result << 7) | (i & 0x7f); + } + while ((i & 0x80) != 0); + + return result; + } + + String readStrI() throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + boolean wsp = true; + while (true){ + int i = in.read(); + if (i == 0){ + break; + } + if (i == -1){ + throw new IOException(UNEXPECTED_EOF); + } + if (i > 32){ + wsp = false; + } + buf.write(i); + } + isWhitespace = wsp; + String result = new String(buf.toByteArray(), encoding); + buf.close(); + return result; + } + + String readStrT() throws IOException { + int pos = readInt(); + // As the main reason of stringTable is compression we build a cache of Strings + // stringTable is supposed to help create Strings from parts which means some cache hit rate + // This will help to minimize the Strings created when invoking readStrT() repeatedly + if (cacheStringTable == null){ + //Lazy init if device is not using StringTable but inline 0x03 strings + cacheStringTable = new Hashtable(); + } + String forReturn = (String) cacheStringTable.get(new Integer(pos)); + if (forReturn == null){ + + int end = pos; + while(end < stringTable.length && stringTable[end] != '\0'){ + end++; + } + forReturn = new String(stringTable, pos, end-pos, encoding); + cacheStringTable.put(new Integer(pos), forReturn); + } + return forReturn; + } + + /** + * Sets the tag table for a given page. + * The first string in the array defines tag 5, the second tag 6 etc. + */ + + public void setTagTable(int page, String[] table) { + setTable(page, TAG_TABLE, table); + + // this.tagTable = tagTable; + // if (page != 0) + // throw new RuntimeException("code pages curr. not supp."); + } + + /** Sets the attribute start Table for a given page. + * The first string in the array defines attribute + * 5, the second attribute 6 etc. Please use the + * character '=' (without quote!) as delimiter + * between the attribute name and the (start of the) value + */ + + public void setAttrStartTable( + int page, + String[] table) { + + setTable(page, ATTR_START_TABLE, table); + } + + /** Sets the attribute value Table for a given page. + * The first string in the array defines attribute value 0x85, + * the second attribute value 0x86 etc. + */ + + public void setAttrValueTable( + int page, + String[] table) { + + setTable(page, ATTR_VALUE_TABLE, table); + } + + /** Returns the token ID for start tags or the event type for wap proprietary events + * such as OPAQUE. + */ + + public int getWapCode(){ + return wapCode; + } + + public Object getWapExtensionData(){ + return wapExtensionData; + } + + +} diff --git a/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java b/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java new file mode 100644 index 0000000..8c1b598 --- /dev/null +++ b/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java @@ -0,0 +1,512 @@ +/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. */ + +//Contributors: Jonathan Cox, Bogdan Onoiu, Jerry Tian + +package org.kxml2.wap; + +import java.io.*; +import java.util.*; + +import org.xmlpull.v1.*; + +// TODO: make some of the "direct" WBXML token writing methods public?? + +/** + * A class for writing WBXML. + * + */ + + + +public class WbxmlSerializer implements XmlSerializer { + + + Hashtable stringTable = new Hashtable(); + + OutputStream out; + + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + ByteArrayOutputStream stringTableBuf = new ByteArrayOutputStream(); + + String pending; + int depth; + String name; + String namespace; + Vector attributes = new Vector(); + + Hashtable attrStartTable = new Hashtable(); + Hashtable attrValueTable = new Hashtable(); + Hashtable tagTable = new Hashtable(); + + private int attrPage; + private int tagPage; + + private String encoding; + + + public XmlSerializer attribute(String namespace, String name, String value) { + attributes.addElement(name); + attributes.addElement(value); + return this; + } + + + public void cdsect (String cdsect) throws IOException{ + text (cdsect); + } + + + + /* silently ignore comment */ + + public void comment (String comment) { + } + + + public void docdecl (String docdecl) { + throw new RuntimeException ("Cannot write docdecl for WBXML"); + } + + + public void entityRef (String er) { + throw new RuntimeException ("EntityReference not supported for WBXML"); + } + + public int getDepth() { + return depth; + } + + + public boolean getFeature (String name) { + return false; + } + + public String getNamespace() { + throw new RuntimeException("NYI"); + } + + public String getName() { + throw new RuntimeException("NYI"); + } + + public String getPrefix(String nsp, boolean create) { + throw new RuntimeException ("NYI"); + } + + + public Object getProperty (String name) { + return null; + } + + public void ignorableWhitespace (String sp) { + } + + + public void endDocument() throws IOException { + writeInt(out, stringTableBuf.size()); + + // write StringTable + + out.write(stringTableBuf.toByteArray()); + + // write buf + + out.write(buf.toByteArray()); + + // ready! + + out.flush(); + } + + + /** ATTENTION: flush cannot work since Wbxml documents require + buffering. Thus, this call does nothing. */ + + public void flush() { + } + + + public void checkPending(boolean degenerated) throws IOException { + if (pending == null) + return; + + int len = attributes.size(); + + int[] idx = (int[]) tagTable.get(pending); + + // if no entry in known table, then add as literal + if (idx == null) { + buf.write( + len == 0 + ? (degenerated ? Wbxml.LITERAL : Wbxml.LITERAL_C) + : (degenerated ? Wbxml.LITERAL_A : Wbxml.LITERAL_AC)); + + writeStrT(pending, false); + } + else { + if(idx[0] != tagPage){ + tagPage=idx[0]; + buf.write(Wbxml.SWITCH_PAGE); + buf.write(tagPage); + } + + buf.write( + len == 0 + ? (degenerated ? idx[1] : idx[1] | 64) + : (degenerated + ? idx[1] | 128 + : idx[1] | 192)); + + } + + for (int i = 0; i < len;) { + idx = (int[]) attrStartTable.get(attributes.elementAt(i)); + + if (idx == null) { + buf.write(Wbxml.LITERAL); + writeStrT((String) attributes.elementAt(i), false); + } + else { + if(idx[0] != attrPage){ + attrPage = idx[0]; + buf.write(0); + buf.write(attrPage); + } + buf.write(idx[1]); + } + idx = (int[]) attrValueTable.get(attributes.elementAt(++i)); + if (idx == null) { + writeStr((String) attributes.elementAt(i)); + } + else { + if(idx[0] != attrPage){ + attrPage = idx[0]; + buf.write(0); + buf.write(attrPage); + } + buf.write(idx[1]); + } + ++i; + } + + if (len > 0) + buf.write(Wbxml.END); + + pending = null; + attributes.removeAllElements(); + } + + + public void processingInstruction(String pi) { + throw new RuntimeException ("PI NYI"); + } + + + public void setFeature(String name, boolean value) { + throw new IllegalArgumentException ("unknown feature "+name); + } + + + + public void setOutput (Writer writer) { + throw new RuntimeException ("Wbxml requires an OutputStream!"); + } + + public void setOutput (OutputStream out, String encoding) throws IOException { + + this.encoding = encoding == null ? "UTF-8" : encoding; + this.out = out; + + buf = new ByteArrayOutputStream(); + stringTableBuf = new ByteArrayOutputStream(); + + // ok, write header + } + + + public void setPrefix(String prefix, String nsp) { + throw new RuntimeException("NYI"); + } + + public void setProperty(String property, Object value) { + throw new IllegalArgumentException ("unknown property "+property); + } + + + public void startDocument(String s, Boolean b) throws IOException{ + out.write(0x03); // version 1.3 + // http://www.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.htm + out.write(0x01); // unknown or missing public identifier + + // default encoding is UTF-8 + + if(s != null){ + encoding = s; + } + + if (encoding.toUpperCase().equals("UTF-8")){ + out.write(106); + }else if (encoding.toUpperCase().equals("ISO-8859-1")){ + out.write(0x04); + }else{ + throw new UnsupportedEncodingException(s); + } + } + + + public XmlSerializer startTag(String namespace, String name) throws IOException { + + if (namespace != null && !"".equals(namespace)) + throw new RuntimeException ("NSP NYI"); + + //current = new State(current, prefixMap, name); + + checkPending(false); + pending = name; + depth++; + + return this; + } + + public XmlSerializer text(char[] chars, int start, int len) throws IOException { + + checkPending(false); + + writeStr(new String(chars, start, len)); + + return this; + } + + public XmlSerializer text(String text) throws IOException { + + checkPending(false); + + writeStr(text); + + return this; + } + + + /** Used in text() and attribute() to write text */ + + private void writeStr(String text) throws IOException{ + int p0 = 0; + int lastCut = 0; + int len = text.length(); + + while(p0 < len){ + while(p0 < len && text.charAt(p0) < 'A' ){ // skip interpunctation + p0++; + } + int p1 = p0; + while(p1 < len && text.charAt(p1) >= 'A'){ + p1++; + } + + if(p1 - p0 > 10) { + + if(p0 > lastCut && text.charAt(p0-1) == ' ' + && stringTable.get(text.substring(p0, p1)) == null){ + + buf.write(Wbxml.STR_T); + writeStrT(text.substring(lastCut, p1), false); + } + else { + + if(p0 > lastCut && text.charAt(p0-1) == ' '){ + p0--; + } + + if(p0 > lastCut){ + buf.write(Wbxml.STR_T); + writeStrT(text.substring(lastCut, p0), false); + } + buf.write(Wbxml.STR_T); + writeStrT(text.substring(p0, p1), true); + } + lastCut = p1; + } + p0 = p1; + } + + if(lastCut < len){ + buf.write(Wbxml.STR_T); + writeStrT(text.substring(lastCut, len), false); + } + } + + + + public XmlSerializer endTag(String namespace, String name) throws IOException { + + // current = current.prev; + + if (pending != null) + checkPending(true); + else + buf.write(Wbxml.END); + + depth--; + + return this; + } + + /** + * @throws IOException */ + + public void writeWapExtension(int type, Object data) throws IOException { + checkPending(false); + buf.write(type); + switch(type){ + case Wbxml.EXT_0: + case Wbxml.EXT_1: + case Wbxml.EXT_2: + break; + + case Wbxml.OPAQUE: + byte[] bytes = (byte[]) data; + writeInt(buf, bytes.length); + buf.write(bytes); + break; + + case Wbxml.EXT_I_0: + case Wbxml.EXT_I_1: + case Wbxml.EXT_I_2: + writeStrI(buf, (String) data); + break; + + case Wbxml.EXT_T_0: + case Wbxml.EXT_T_1: + case Wbxml.EXT_T_2: + writeStrT((String) data, false); + break; + + default: + throw new IllegalArgumentException(); + } + } + + // ------------- internal methods -------------------------- + + static void writeInt(OutputStream out, int i) throws IOException { + byte[] buf = new byte[5]; + int idx = 0; + + do { + buf[idx++] = (byte) (i & 0x7f); + i = i >> 7; + } + while (i != 0); + + while (idx > 1) { + out.write(buf[--idx] | 0x80); + } + out.write(buf[0]); + } + + void writeStrI(OutputStream out, String s) throws IOException { + byte[] data = s.getBytes(encoding); + out.write(data); + out.write(0); + } + + private final void writeStrT(String s, boolean mayPrependSpace) throws IOException { + + Integer idx = (Integer) stringTable.get(s); + + if (idx != null) { + writeInt(buf, idx.intValue()); + } + else{ + int i = stringTableBuf.size(); + if(s.charAt(0) >= '0' && mayPrependSpace){ + s = ' ' + s; + writeInt(buf, i+1); + } + else{ + writeInt(buf, i); + } + + stringTable.put(s, new Integer(i)); + if(s.charAt(0) == ' '){ + stringTable.put(s.substring(1), new Integer(i+1)); + } + int j = s.lastIndexOf(' '); + if(j > 1){ + stringTable.put(s.substring(j), new Integer(i+j)); + stringTable.put(s.substring(j+1), new Integer(i+j+1)); + } + + writeStrI(stringTableBuf, s); + stringTableBuf.flush(); + } + + } + + /** + * Sets the tag table for a given page. + * The first string in the array defines tag 5, the second tag 6 etc. + */ + + public void setTagTable(int page, String[] tagTable) { + // TODO: clear entries in tagTable? + + for (int i = 0; i < tagTable.length; i++) { + if (tagTable[i] != null) { + Object idx = new int[]{page, i+5}; + this.tagTable.put(tagTable[i], idx); + } + } + } + + /** + * Sets the attribute start Table for a given page. + * The first string in the array defines attribute + * 5, the second attribute 6 etc. + * Please use the + * character '=' (without quote!) as delimiter + * between the attribute name and the (start of the) value + */ + public void setAttrStartTable(int page, String[] attrStartTable) { + + for (int i = 0; i < attrStartTable.length; i++) { + if (attrStartTable[i] != null) { + Object idx = new int[] {page, i + 5}; + this.attrStartTable.put(attrStartTable[i], idx); + } + } + } + + /** + * Sets the attribute value Table for a given page. + * The first string in the array defines attribute value 0x85, + * the second attribute value 0x86 etc. + */ + public void setAttrValueTable(int page, String[] attrValueTable) { + // clear entries in this.table! + for (int i = 0; i < attrValueTable.length; i++) { + if (attrValueTable[i] != null) { + Object idx = new int[]{page, i + 0x085}; + this.attrValueTable.put(attrValueTable[i], idx); + } + } + } +} diff --git a/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java b/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java new file mode 100644 index 0000000..5ea8496 --- /dev/null +++ b/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java @@ -0,0 +1,192 @@ +package org.kxml2.wap.syncml; + +import org.kxml2.wap.*; + +public abstract class SyncML { + + + // SyncML-Common (-//SYNCML//DTD SyncML 1.2//EN and -//SYNCML//DTD MetInf 1.2//EN) support + + public static WbxmlParser createParser() { + WbxmlParser p = new WbxmlParser(); + p.setTagTable(0, TAG_TABLE_0); + p.setTagTable(1, TAG_TABLE_1); + return p; + } + + public static WbxmlSerializer createSerializer() { + WbxmlSerializer s = new WbxmlSerializer(); + s.setTagTable(0, TAG_TABLE_0); + s.setTagTable(1, TAG_TABLE_1); + return s; + } + + + // SyncML-Common + DMDDF (-//OMA//DTD-DM-DDF 1.2//EN) support + + public static WbxmlParser createDMParser() { + WbxmlParser p = createParser(); + p.setTagTable(2, TAG_TABLE_2_DM); + return p; + } + + public static WbxmlSerializer createDMSerializer() { + WbxmlSerializer s = createSerializer(); + s.setTagTable(2, TAG_TABLE_2_DM); + return s; + } + + // Tables + + public static final String [] TAG_TABLE_0 = { + + // -//SYNCML//DTD SyncML 1.2//EN + + "Add", // 0x05 + "Alert", // 0x06 + "Archive", // 0x07 + "Atomic", // 0x08 + "Chal", // 0x09 + "Cmd", // 0x0a + "CmdID", // 0x0b + "CmdRef", // 0x0c + "Copy", // 0x0d + "Cred", // 0x0e + "Data", // 0x0f + "Delete", // 0x10 + "Exec", // 0x11 + "Final", // 0x12 + "Get", // 0x13 + "Item", // 0x14 + "Lang", // 0x15 + "LocName", // 0x16 + "LocURI", // 0x17 + "Map", // 0x18 + "MapItem", // 0x19 + "Meta", // 0x1a + "MsgID", // 0x1b + "MsgRef", // 0x1c + "NoResp", // 0x1d + "NoResults", // 0x1e + "Put", // 0x1f + "Replace", // 0x20 + "RespURI", // 0x21 + "Results", // 0x22 + "Search", // 0x23 + "Sequence", // 0x24 + "SessionID", // 0x25 + "SftDel", // 0x26 + "Source", // 0x27 + "SourceRef", // 0x28 + "Status", // 0x29 + "Sync", // 0x2a + "SyncBody", // 0x2b + "SyncHdr", // 0x2c + "SyncML", // 0x2d + "Target", // 0x2e + "TargetRef", // 0x2f + "Reserved for future use", // 0x30 + "VerDTD", // 0x31 + "VerProto", // 0x32 + "NumberOfChanged",// 0x33 + "MoreData", // 0x34 + "Field", // 0x35 + "Filter", // 0x36 + "Record", // 0x37 + "FilterType", // 0x38 + "SourceParent", // 0x39 + "TargetParent", // 0x3a + "Move", // 0x3b + "Correlator" // 0x3c + }; + + public static final String [] TAG_TABLE_1 = { + + // -//SYNCML//DTD MetInf 1.2//EN + + "Anchor", // 0x05 + "EMI", // 0x06 + "Format", // 0x07 + "FreeID", // 0x08 + "FreeMem", // 0x09 + "Last", // 0x0a + "Mark", // 0x0b + "MaxMsgSize", // 0x0c + "Mem", // 0x0d + "MetInf", // 0x0e + "Next", // 0x0f + "NextNonce", // 0x10 + "SharedMem", // 0x11 + "Size", // 0x12 + "Type", // 0x13 + "Version", // 0x14 + "MaxObjSize", // 0x15 + "FieldLevel" // 0x16 + + }; + + public static final String [] TAG_TABLE_2_DM = { + + // -//OMA//DTD-DM-DDF 1.2//EN + + "AccessType", // 0x05 + "ACL", // 0x06 + "Add", // 0x07 + "b64", // 0x08 + "bin", // 0x09 + "bool", // 0x0a + "chr", // 0x0b + "CaseSense", // 0x0c + "CIS", // 0x0d + "Copy", // 0x0e + "CS", // 0x0f + "date", // 0x10 + "DDFName", // 0x11 + "DefaultValue", // 0x12 + "Delete", // 0x13 + "Description", // 0x14 + "DDFFormat", // 0x15 + "DFProperties", // 0x16 + "DFTitle", // 0x17 + "DFType", // 0x18 + "Dynamic", // 0x19 + "Exec", // 0x1a + "float", // 0x1b + "Format", // 0x1c + "Get", // 0x1d + "int", // 0x1e + "Man", // 0x1f + "MgmtTree", // 0x20 + "MIME", // 0x21 + "Mod", // 0x22 + "Name", // 0x23 + "Node", // 0x24 + "node", // 0x25 + "NodeName", // 0x26 + "null", // 0x27 + "Occurence", // 0x28 + "One", // 0x29 + "OneOrMore", // 0x2a + "OneOrN", // 0x2b + "Path", // 0x2c + "Permanent", // 0x2d + "Replace", // 0x2e + "RTProperties", // 0x2f + "Scope", // 0x30 + "Size", // 0x31 + "time", // 0x32 + "Title", // 0x33 + "TStamp", // 0x34 + "Type", // 0x35 + "Value", // 0x36 + "VerDTD", // 0x37 + "VerNo", // 0x38 + "xml", // 0x39 + "ZeroOrMore", // 0x3a + "ZeroOrN", // 0x3b + "ZeroOrOne" // 0x3c + + }; + +} + diff --git a/xml/src/main/java/org/kxml2/wap/wml/Wml.java b/xml/src/main/java/org/kxml2/wap/wml/Wml.java new file mode 100644 index 0000000..7e925d8 --- /dev/null +++ b/xml/src/main/java/org/kxml2/wap/wml/Wml.java @@ -0,0 +1,233 @@ +package org.kxml2.wap.wml; + +import org.kxml2.wap.*; + + +/** This class contains the wml coding tables for elements + * and attributes needed by the WmlParser. + */ + + +public abstract class Wml { + + /** Creates a WbxmlParser with the WML code pages set */ + + public static WbxmlParser createParser() { + WbxmlParser p = new WbxmlParser(); + p.setTagTable(0, TAG_TABLE); + p.setAttrStartTable(0, ATTR_START_TABLE); + p.setAttrValueTable(0, ATTR_VALUE_TABLE); + return p; + } + + public static WbxmlSerializer createSerializer() { + WbxmlSerializer s = new WbxmlSerializer(); + s.setTagTable(0, TAG_TABLE); + s.setAttrStartTable(0, ATTR_START_TABLE); + s.setAttrValueTable(0, ATTR_VALUE_TABLE); + return s; + } + + + public static final String [] TAG_TABLE = { + + null, // 05 + null, // 06 + null, // 07 + null, // 08 + null, // 09 + null, // 0A + null, // 0B + null, // 0C + null, // 0D + null, // 0E + null, // 0F + + null, // 10 + null, // 11 + null, // 12 + null, // 13 + null, // 14 + null, // 15 + null, // 16 + null, // 17 + null, // 18 + null, // 19 + null, // 1A + null, // 1B + "a", // 1C + "td", // 1D + "tr", // 1E + "table", // 1F + + "p", // 20 + "postfield", // 21 + "anchor", // 22 + "access", // 23 + "b", // 24 + "big", // 25 + "br", // 26 + "card", // 27 + "do", // 28 + "em", // 29 + "fieldset", // 2A + "go", // 2B + "head", // 2C + "i", // 2D + "img", // 2E + "input", // 2F + + "meta", // 30 + "noop", // 31 + "prev", // 32 + "onevent", // 33 + "optgroup", // 34 + "option", // 35 + "refresh", // 36 + "select", // 37 + "small", // 38 + "strong", // 39 + null, // 3A + "template", // 3B + "timer", // 3C + "u", // 3D + "setvar", // 3E + "wml", // 3F + }; + + + public static final String [] ATTR_START_TABLE = { + "accept-charset", // 05 + "align=bottom", // 06 + "align=center", // 07 + "align=left", // 08 + "align=middle", // 09 + "align=right", // 0A + "align=top", // 0B + "alt", // 0C + "content", // 0D + null, // 0E + "domain", // 0F + + "emptyok=false", // 10 + "emptyok=true", // 11 + "format", // 12 + "height", // 13 + "hspace", // 14 + "ivalue", // 15 + "iname", // 16 + null, // 17 + "label", // 18 + "localsrc", // 19 + "maxlength", // 1A + "method=get", // 1B + "method=post", // 1C + "mode=nowrap", // 1D + "mode=wrap", // 1E + "multiple=false", // 1F + + "multiple=true", // 20 + "name", // 21 + "newcontext=false", // 22 + "newcontext=true", // 23 + "onpick", // 24 + "onenterbackward", // 25 + "onenterforward", // 26 + "ontimer", // 27 + "optimal=false", // 28 + "optimal=true", // 29 + "path", // 2A + null, // 2B + null, // 2C + null, // 2D + "scheme", // 2E + "sendreferer=false", // 2F + + "sendreferer=true", // 30 + "size", // 31 + "src", // 32 + "ordered=true", // 33 + "ordered=false", // 34 + "tabindex", // 35 + "title", // 36 + "type", // 37 + "type=accept", // 38 + "type=delete", // 39 + "type=help", // 3A + "type=password", // 3B + "type=onpick", // 3C + "type=onenterbackward", // 3D + "type=onenterforward", // 3E + "type=ontimer", // 3F + + null, // 40 + null, // 41 + null, // 42 + null, // 43 + null, // 44 + "type=options", // 45 + "type=prev", // 46 + "type=reset", // 47 + "type=text", // 48 + "type=vnd.", // 49 + "href", // 4A + "href=http://", // 4B + "href=https://", // 4C + "value", // 4D + "vspace", // 4E + "width", // 4F + + "xml:lang", // 50 + null, // 51 + "align", // 52 + "columns", // 53 + "class", // 54 + "id", // 55 + "forua=false", // 56 + "forua=true", // 57 + "src=http://", // 58 + "src=https://", // 59 + "http-equiv", // 5A + "http-equiv=Content-Type", // 5B + "content=application/vnd.wap.wmlc;charset=", // 5C + "http-equiv=Expires", // 5D + null, // 5E + null, // 5F + }; + + + public static final String [] ATTR_VALUE_TABLE = { + ".com/", // 85 + ".edu/", // 86 + ".net/", // 87 + ".org/", // 88 + "accept", // 89 + "bottom", // 8A + "clear", // 8B + "delete", // 8C + "help", // 8D + "http://", // 8E + "http://www.", // 8F + + "https://", // 90 + "https://www.", // 91 + null, // 92 + "middle", // 93 + "nowrap", // 94 + "onpick", // 95 + "onenterbackward", // 96 + "onenterforward", // 97 + "ontimer", // 98 + "options", // 99 + "password", // 9A + "reset", // 9B + null, // 9C + "text", // 9D + "top", // 9E + "unknown", // 9F + + "wrap", // A0 + "www.", // A1 + }; +} + diff --git a/xml/src/main/java/org/kxml2/wap/wv/WV.java b/xml/src/main/java/org/kxml2/wap/wv/WV.java new file mode 100644 index 0000000..e2afbfb --- /dev/null +++ b/xml/src/main/java/org/kxml2/wap/wv/WV.java @@ -0,0 +1,593 @@ +package org.kxml2.wap.wv; + +import java.io.IOException; + +import org.kxml2.wap.*; + +/* + + * WV.java + + * + + * Created on 25 September 2003, 10:40 + + */ + + + + + + /** + * Wireless Village CSP 1.1 ("OMA-WV-CSP-V1_1-20021001-A.pdf") + * Wireless Village CSP 1.2 ("OMA-IMPS-WV-CSP_WBXML-v1_2-20030221-C.PDF") + * There are some bugs in the 1.2 spec but this is Ok. 1.2 is candidate + * + + * @author Bogdan Onoiu + + */ + +public abstract class WV { + + + + + + public static WbxmlParser createParser () throws IOException { + + WbxmlParser parser = new WbxmlParser(); + + parser.setTagTable (0, WV.tagTablePage0); + parser.setTagTable (1, WV.tagTablePage1); + parser.setTagTable (2, WV.tagTablePage2); + parser.setTagTable (3, WV.tagTablePage3); + parser.setTagTable (4, WV.tagTablePage4); + parser.setTagTable (5, WV.tagTablePage5); + parser.setTagTable (6, WV.tagTablePage6); + parser.setTagTable (7, WV.tagTablePage7); + parser.setTagTable (8, WV.tagTablePage8); + parser.setTagTable (9, WV.tagTablePage9); + parser.setTagTable (10, WV.tagTablePageA); + + parser.setAttrStartTable (0, WV.attrStartTable); + + parser.setAttrValueTable (0, WV.attrValueTable); + + return parser; + } + + + + public static final String [] tagTablePage0 = { + /* Common ... continue on Page 0x09 */ + "Acceptance", //0x00, 0x05 + "AddList", //0x00, 0x06 + "AddNickList", //0x00, 0x07 + "SName", //0x00, 0x08 + "WV-CSP-Message", //0x00, 0x09 + "ClientID", //0x00, 0x0A + "Code", //0x00, 0x0B + "ContactList", //0x00, 0x0C + "ContentData", //0x00, 0x0D + "ContentEncoding",//0x00, 0x0E + "ContentSize", //0x00, 0x0F + "ContentType", //0x00, 0x10 + "DateTime", //0x00, 0x11 + "Description", //0x00, 0x12 + "DetailedResult", //0x00, 0x13 + "EntityList", //0x00, 0x14 + "Group", //0x00, 0x15 + "GroupID", //0x00, 0x16 + "GroupList", //0x00, 0x17 + "InUse", //0x00, 0x18 + "Logo", //0x00, 0x19 + "MessageCount", //0x00, 0x1A + "MessageID", //0x00, 0x1B + "MessageURI", //0x00, 0x1C + "MSISDN", //0x00, 0x1D + "Name", //0x00, 0x1E + "NickList", //0x00, 0x1F + "NickName", //0x00, 0x20 + "Poll", //0x00, 0x21 + "Presence", //0x00, 0x22 + "PresenceSubList",//0x00, 0x23 + "PresenceValue", //0x00, 0x24 + "Property", //0x00, 0x25 + "Qualifier", //0x00, 0x26 + "Recipient", //0x00, 0x27 + "RemoveList", //0x00, 0x28 + "RemoveNickList", //0x00, 0x29 + "Result", //0x00, 0x2A + "ScreenName", //0x00, 0x2B + "Sender", //0x00, 0x2C + "Session", //0x00, 0x2D + "SessionDescriptor",//0x00, 0x2E + "SessionID", //0x00, 0x2F + "SessionType", //0x00, 0x30 + "Status", //0x00, 0x31 + "Transaction", //0x00, 0x32 + "TransactionContent",//0x00, 0x33 + "TransactionDescriptor",//0x00, 0x34 + "TransactionID", //0x00, 0x35 + "TransactionMode",//0x00, 0x36 + "URL", //0x00, 0x37 + "URLList", //0x00, 0x38 + "User", //0x00, 0x39 + "UserID", //0x00, 0x3A + "UserList", //0x00, 0x3B + "Validity", //0x00, 0x3C + "Value", //0x00, 0x3D + }; + + public static final String [] tagTablePage1 = { + /* Access ... continue on Page 0x0A */ + "AllFunctions", // 0x01, 0x05 + "AllFunctionsRequest", // 0x01, 0x06 + "CancelInvite-Request", // 0x01, 0x07 + "CancelInviteUser-Request", // 0x01, 0x08 + "Capability", // 0x01, 0x09 + "CapabilityList", // 0x01, 0x0A + "CapabilityRequest", // 0x01, 0x0B + "ClientCapability-Request", // 0x01, 0x0C + "ClientCapability-Response",// 0x01, 0x0D + "DigestBytes", // 0x01, 0x0E + "DigestSchema", // 0x01, 0x0F + "Disconnect", // 0x01, 0x10 + "Functions", // 0x01, 0x11 + "GetSPInfo-Request", // 0x01, 0x12 + "GetSPInfo-Response", // 0x01, 0x13 + "InviteID", // 0x01, 0x14 + "InviteNote", // 0x01, 0x15 + "Invite-Request", // 0x01, 0x16 + "Invite-Response", // 0x01, 0x17 + "InviteType", // 0x01, 0x18 + "InviteUser-Request", // 0x01, 0x19 + "InviteUser-Response", // 0x01, 0x1A + "KeepAlive-Request", // 0x01, 0x1B + "KeepAliveTime", // 0x01, 0x1C + "Login-Request", // 0x01, 0x1D + "Login-Response", // 0x01, 0x1E + "Logout-Request", // 0x01, 0x1F + "Nonce", // 0x01, 0x20 + "Password", // 0x01, 0x21 + "Polling-Request", // 0x01, 0x22 + "ResponseNote", // 0x01, 0x23 + "SearchElement", // 0x01, 0x24 + "SearchFindings", // 0x01, 0x25 + "SearchID", // 0x01, 0x26 + "SearchIndex", // 0x01, 0x27 + "SearchLimit", // 0x01, 0x28 + "KeepAlive-Response", // 0x01, 0x29 + "SearchPairList", // 0x01, 0x2A + "Search-Request", // 0x01, 0x2B + "Search-Response", // 0x01, 0x2C + "SearchResult", // 0x01, 0x2D + "Service-Request", // 0x01, 0x2E + "Service-Response", // 0x01, 0x2F + "SessionCookie", // 0x01, 0x30 + "StopSearch-Request", // 0x01, 0x31 + "TimeToLive", // 0x01, 0x32 + "SearchString", // 0x01, 0x33 + "CompletionFlag", // 0x01, 0x34 + null, // 0x01, 0x35 + "ReceiveList", // 0x01, 0x36 /* WV 1.2 */ + "VerifyID-Request", // 0x01, 0x37 /* WV 1.2 */ + "Extended-Request", // 0x01, 0x38 /* WV 1.2 */ + "Extended-Response", // 0x01, 0x39 /* WV 1.2 */ + "AgreedCapabilityList", // 0x01, 0x3A /* WV 1.2 */ + "Extended-Data", // 0x01, 0x3B /* WV 1.2 */ + "OtherServer", // 0x01, 0x3C /* WV 1.2 */ + "PresenceAttributeNSName",//0x01, 0x3D /* WV 1.2 */ + "SessionNSName", // 0x01, 0x3E /* WV 1.2 */ + "TransactionNSName", // 0x01, 0x3F /* WV 1.2 */ + }; + + public static final String [] tagTablePage2 = { + /* Service ... continue on Page 0x08 */ + "ADDGM", // 0x02, 0x05 + "AttListFunc", // 0x02, 0x06 + "BLENT", // 0x02, 0x07 + "CAAUT", // 0x02, 0x08 + "CAINV", // 0x02, 0x09 + "CALI", // 0x02, 0x0A + "CCLI", // 0x02, 0x0B + "ContListFunc", // 0x02, 0x0C + "CREAG", // 0x02, 0x0D + "DALI", // 0x02, 0x0E + "DCLI", // 0x02, 0x0F + "DELGR", // 0x02, 0x10 + "FundamentalFeat",//0x02, 0x11 + "FWMSG", // 0x02, 0x12 + "GALS", // 0x02, 0x13 + "GCLI", // 0x02, 0x14 + "GETGM", // 0x02, 0x15 + "GETGP", // 0x02, 0x16 + "GETLM", // 0x02, 0x17 + "GETM", // 0x02, 0x18 + "GETPR", // 0x02, 0x19 + "GETSPI", // 0x02, 0x1A + "GETWL", // 0x02, 0x1B + "GLBLU", // 0x02, 0x1C + "GRCHN", // 0x02, 0x1D + "GroupAuthFunc",// 0x02, 0x1E + "GroupFeat", // 0x02, 0x1F + "GroupMgmtFunc",// 0x02, 0x20 + "GroupUseFunc", // 0x02, 0x21 + "IMAuthFunc", // 0x02, 0x22 + "IMFeat", // 0x02, 0x23 + "IMReceiveFunc",// 0x02, 0x24 + "IMSendFunc", // 0x02, 0x25 + "INVIT", // 0x02, 0x26 + "InviteFunc", // 0x02, 0x27 + "MBRAC", // 0x02, 0x28 + "MCLS", // 0x02, 0x29 + "MDELIV", // 0x02, 0x2A + "NEWM", // 0x02, 0x2B + "NOTIF", // 0x02, 0x2C + "PresenceAuthFunc",//0x02, 0x2D + "PresenceDeliverFunc",//0x02, 0x2E + "PresenceFeat", // 0x02, 0x2F + "REACT", // 0x02, 0x30 + "REJCM", // 0x02, 0x31 + "REJEC", // 0x02, 0x32 + "RMVGM", // 0x02, 0x33 + "SearchFunc", // 0x02, 0x34 + "ServiceFunc", // 0x02, 0x35 + "SETD", // 0x02, 0x36 + "SETGP", // 0x02, 0x37 + "SRCH", // 0x02, 0x38 + "STSRC", // 0x02, 0x39 + "SUBGCN", // 0x02, 0x3A + "UPDPR", // 0x02, 0x3B + "WVCSPFeat", // 0x02, 0x3C + "MF", // 0x02, 0x3D /* WV 1.2 */ + "MG", // 0x02, 0x3E /* WV 1.2 */ + "MM" // 0x02, 0x3F /* WV 1.2 */ + }; + + public static final String [] tagTablePage3 = { + /* Client Capability */ + "AcceptedCharset", // 0x03, 0x05 + "AcceptedContentLength", // 0x03, 0x06 + "AcceptedContentType", // 0x03, 0x07 + "AcceptedTransferEncoding", // 0x03, 0x08 + "AnyContent", // 0x03, 0x09 + "DefaultLanguage", // 0x03, 0x0A + "InitialDeliveryMethod", // 0x03, 0x0B + "MultiTrans", // 0x03, 0x0C + "ParserSize", // 0x03, 0x0D + "ServerPollMin", // 0x03, 0x0E + "SupportedBearer", // 0x03, 0x0F + "SupportedCIRMethod", // 0x03, 0x10 + "TCPAddress", // 0x03, 0x11 + "TCPPort", // 0x03, 0x12 + "UDPPort" // 0x03, 0x13 + }; + + public static final String [] tagTablePage4 = { + /* Presence Primitive */ + "CancelAuth-Request", // 0x04, 0x05 + "ContactListProperties", // 0x04, 0x06 + "CreateAttributeList-Request", // 0x04, 0x07 + "CreateList-Request", // 0x04, 0x08 + "DefaultAttributeList", // 0x04, 0x09 + "DefaultContactList", // 0x04, 0x0A + "DefaultList", // 0x04, 0x0B + "DeleteAttributeList-Request", // 0x04, 0x0C + "DeleteList-Request", // 0x04, 0x0D + "GetAttributeList-Request", // 0x04, 0x0E + "GetAttributeList-Response", // 0x04, 0x0F + "GetList-Request", // 0x04, 0x10 + "GetList-Response", // 0x04, 0x11 + "GetPresence-Request", // 0x04, 0x12 + "GetPresence-Response", // 0x04, 0x13 + "GetWatcherList-Request", // 0x04, 0x14 + "GetWatcherList-Response", // 0x04, 0x15 + "ListManage-Request", // 0x04, 0x16 + "ListManage-Response", // 0x04, 0x17 + "UnsubscribePresence-Request", // 0x04, 0x18 + "PresenceAuth-Request", // 0x04, 0x19 + "PresenceAuth-User", // 0x04, 0x1A + "PresenceNotification-Request", // 0x04, 0x1B + "UpdatePresence-Request", // 0x04, 0x1C + "SubscribePresence-Request", // 0x04, 0x1D + "Auto-Subscribe", // 0x04, 0x1E /* WV 1.2 */ + "GetReactiveAuthStatus-Request",// 0x04, 0x1F /* WV 1.2 */ + "GetReactiveAuthStatus-Response",// 0x04, 0x20 /* WV 1.2 */ + }; + + public static final String [] tagTablePage5 = { + /* Presence Attribute */ + "Accuracy", // 0x05, 0x05 + "Address", // 0x05, 0x06 + "AddrPref", // 0x05, 0x07 + "Alias", // 0x05, 0x08 + "Altitude", // 0x05, 0x09 + "Building", // 0x05, 0x0A + "Caddr", // 0x05, 0x0B + "City", // 0x05, 0x0C + "ClientInfo", // 0x05, 0x0D + "ClientProducer", // 0x05, 0x0E + "ClientType", // 0x05, 0x0F + "ClientVersion", // 0x05, 0x10 + "CommC", // 0x05, 0x11 + "CommCap", // 0x05, 0x12 + "ContactInfo", // 0x05, 0x13 + "ContainedvCard", // 0x05, 0x14 + "Country", // 0x05, 0x15 + "Crossing1", // 0x05, 0x16 + "Crossing2", // 0x05, 0x17 + "DevManufacturer", // 0x05, 0x18 + "DirectContent", // 0x05, 0x19 + "FreeTextLocation", // 0x05, 0x1A + "GeoLocation", // 0x05, 0x1B + "Language", // 0x05, 0x1C + "Latitude", // 0x05, 0x1D + "Longitude", // 0x05, 0x1E + "Model", // 0x05, 0x1F + "NamedArea", // 0x05, 0x20 + "OnlineStatus", // 0x05, 0x21 + "PLMN", // 0x05, 0x22 + "PrefC", // 0x05, 0x23 + "PreferredContacts",// 0x05, 0x24 + "PreferredLanguage",// 0x05, 0x25 + "PreferredContent", // 0x05, 0x26 + "PreferredvCard", // 0x05, 0x27 + "Registration", // 0x05, 0x28 + "StatusContent", // 0x05, 0x29 + "StatusMood", // 0x05, 0x2A + "StatusText", // 0x05, 0x2B + "Street", // 0x05, 0x2C + "TimeZone", // 0x05, 0x2D + "UserAvailability", // 0x05, 0x2E + "Cap", // 0x05, 0x2F + "Cname", // 0x05, 0x30 + "Contact", // 0x05, 0x31 + "Cpriority", // 0x05, 0x32 + "Cstatus", // 0x05, 0x33 + "Note", // 0x05, 0x34 /* WV 1.2 */ + "Zone", // 0x05, 0x35 + null, + "Inf_link", // 0x05, 0x37 /* WV 1.2 */ + "InfoLink", // 0x05, 0x38 /* WV 1.2 */ + "Link", // 0x05, 0x39 /* WV 1.2 */ + "Text", // 0x05, 0x3A /* WV 1.2 */ + }; + + public static final String [] tagTablePage6 = { + /* Messaging */ + "BlockList", // 0x06, 0x05 +// "BlockUser-Request", // 0x06, 0x06 //This is a bug in the spec + "BlockEntity-Request", // 0x06, 0x06 + "DeliveryMethod", // 0x06, 0x07 + "DeliveryReport", // 0x06, 0x08 + "DeliveryReport-Request", // 0x06, 0x09 + "ForwardMessage-Request", // 0x06, 0x0A + "GetBlockedList-Request", // 0x06, 0x0B + "GetBlockedList-Response", // 0x06, 0x0C + "GetMessageList-Request", // 0x06, 0x0D + "GetMessageList-Response", // 0x06, 0x0E + "GetMessage-Request", // 0x06, 0x0F + "GetMessage-Response", // 0x06, 0x10 + "GrantList", // 0x06, 0x11 + "MessageDelivered", // 0x06, 0x12 + "MessageInfo", // 0x06, 0x13 + "MessageNotification", // 0x06, 0x14 + "NewMessage", // 0x06, 0x15 + "RejectMessage-Request", // 0x06, 0x16 + "SendMessage-Request", // 0x06, 0x17 + "SendMessage-Response", // 0x06, 0x18 + "SetDeliveryMethod-Request",// 0x06, 0x19 + "DeliveryTime", // 0x06, 0x1A + }; + + public static final String [] tagTablePage7 = { + /* Group */ + "AddGroupMembers-Request", // 0x07, 0x05 + "Admin", // 0x07, 0x06 + "CreateGroup-Request", // 0x07, 0x07 + "DeleteGroup-Request", // 0x07, 0x08 + "GetGroupMembers-Request", // 0x07, 0x09 + "GetGroupMembers-Response", // 0x07, 0x0A + "GetGroupProps-Request", // 0x07, 0x0B + "GetGroupProps-Response", // 0x07, 0x0C + "GroupChangeNotice", // 0x07, 0x0D + "GroupProperties", // 0x07, 0x0E + "Joined", // 0x07, 0x0F + "JoinedRequest", // 0x07, 0x10 + "JoinGroup-Request", // 0x07, 0x11 + "JoinGroup-Response", // 0x07, 0x12 + "LeaveGroup-Request", // 0x07, 0x13 + "LeaveGroup-Response", // 0x07, 0x14 + "Left", // 0x07, 0x15 + "MemberAccess-Request", // 0x07, 0x16 + "Mod", // 0x07, 0x17 + "OwnProperties", // 0x07, 0x18 + "RejectList-Request", // 0x07, 0x19 + "RejectList-Response", // 0x07, 0x1A + "RemoveGroupMembers-Request",// 0x07, 0x1B + "SetGroupProps-Request", // 0x07, 0x1C + "SubscribeGroupNotice-Request", // 0x07, 0x1D + "SubscribeGroupNotice-Response",// 0x07, 0x1E + "Users", // 0x07, 0x1F + "WelcomeNote", // 0x07, 0x20 + "JoinGroup", // 0x07, 0x21 + "SubscribeNotification", // 0x07, 0x22 + "SubscribeType", // 0x07, 0x23 + "GetJoinedUsers-Request", // 0x07, 0x24 /* WV 1.2 */ + "GetJoinedUsers-Response", // 0x07, 0x25 /* WV 1.2 */ + "AdminMapList", // 0x07, 0x26 /* WV 1.2 */ + "AdminMapping", // 0x07, 0x27 /* WV 1.2 */ + "Mapping", // 0x07, 0x28 /* WV 1.2 */ + "ModMapping", // 0x07, 0x29 /* WV 1.2 */ + "UserMapList", // 0x07, 0x2A /* WV 1.2 */ + "UserMapping", // 0x07, 0x2B /* WV 1.2 */ + }; + + public static final String [] tagTablePage8 = { + /* Service ... continued */ + "MP", // 0x08, 0x05 /* WV 1.2 */ + "GETAUT", // 0x08, 0x06 /* WV 1.2 */ + "GETJU", // 0x08, 0x07 /* WV 1.2 */ + "VRID", // 0x08, 0x08 /* WV 1.2 */ + "VerifyIDFunc", // 0x08, 0x09 /* WV 1.2 */ + }; + + public static final String [] tagTablePage9 = { + /* Common ... continued */ + "CIR", // 0x09, 0x05 /* WV 1.2 */ + "Domain", // 0x09, 0x06 /* WV 1.2 */ + "ExtBlock", // 0x09, 0x07 /* WV 1.2 */ + "HistoryPeriod", // 0x09, 0x08 /* WV 1.2 */ + "IDList", // 0x09, 0x09 /* WV 1.2 */ + "MaxWatcherList", // 0x09, 0x0A /* WV 1.2 */ + "ReactiveAuthState", // 0x09, 0x0B /* WV 1.2 */ + "ReactiveAuthStatus", // 0x09, 0x0C /* WV 1.2 */ + "ReactiveAuthStatusList", // 0x09, 0x0D /* WV 1.2 */ + "Watcher", // 0x09, 0x0E /* WV 1.2 */ + "WatcherStatus" // 0x09, 0x0F /* WV 1.2 */ + }; + + public static final String [] tagTablePageA = { + /* Access ... continued */ + "WV-CSP-NSDiscovery-Request", //0x0A, 0x05 /* WV 1.2 */ + "WV-CSP-NSDiscovery-Response", //0x0A, 0x06 /* WV 1.2 */ + "VersionList" //0x0A, 0x07 /* WV 1.2 */ + }; + + public static final String [] attrStartTable = { + "xmlns=http://www.wireless-village.org/CSP",// 0x00, 0x05 + "xmlns=http://www.wireless-village.org/PA", // 0x00, 0x06 + "xmlns=http://www.wireless-village.org/TRC",// 0x00, 0x07 + "xmlns=http://www.openmobilealliance.org/DTD/WV-CSP", // 0x00, 0x08 + "xmlns=http://www.openmobilealliance.org/DTD/WV-PA", // 0x00, 0x09 + "xmlns=http://www.openmobilealliance.org/DTD/WV-TRC", // 0x00, 0x0A + }; + + public static final String [] attrValueTable = { + + "AccessType", // 0x00 /* Common value token */ + "ActiveUsers", // 0x01 /* Common value token */ + "Admin", // 0x02 /* Common value token */ + "application/", // 0x03 /* Common value token */ + "application/vnd.wap.mms-message", // 0x04 /* Common value token */ + "application/x-sms", // 0x05 /* Common value token */ + "AutoJoin", // 0x06 /* Common value token */ + "BASE64", // 0x07 /* Common value token */ + "Closed", // 0x08 /* Common value token */ + "Default", // 0x09 /* Common value token */ + "DisplayName", // 0x0a /* Common value token */ + "F", // 0x0b /* Common value token */ + "G", // 0x0c /* Common value token */ + "GR", // 0x0d /* Common value token */ + "http://", // 0x0e /* Common value token */ + "https://", // 0x0f /* Common value token */ + "image/", // 0x10 /* Common value token */ + "Inband", // 0x11 /* Common value token */ + "IM", // 0x12 /* Common value token */ + "MaxActiveUsers", // 0x13 /* Common value token */ + "Mod", // 0x14 /* Common value token */ + "Name", // 0x15 /* Common value token */ + "None", // 0x16 /* Common value token */ + "N", // 0x17 /* Common value token */ + "Open", // 0x18 /* Common value token */ + "Outband", // 0x19 /* Common value token */ + "PR", // 0x1a /* Common value token */ + "Private", // 0x1b /* Common value token */ + "PrivateMessaging", // 0x1c /* Common value token */ + "PrivilegeLevel", // 0x1d /* Common value token */ + "Public", // 0x1e /* Common value token */ + "P", // 0x1f /* Common value token */ + "Request", // 0x20 /* Common value token */ + "Response", // 0x21 /* Common value token */ + "Restricted", // 0x22 /* Common value token */ + "ScreenName", // 0x23 /* Common value token */ + "Searchable", // 0x24 /* Common value token */ + "S", // 0x25 /* Common value token */ + "SC", // 0x26 /* Common value token */ + "text/", // 0x27 /* Common value token */ + "text/plain", // 0x28 /* Common value token */ + "text/x-vCalendar", // 0x29 /* Common value token */ + "text/x-vCard", // 0x2a /* Common value token */ + "Topic", // 0x2b /* Common value token */ + "T", // 0x2c /* Common value token */ + "Type", // 0x2d /* Common value token */ + "U", // 0x2e /* Common value token */ + "US", // 0x2f /* Common value token */ + "www.wireless-village.org", // 0x30 /* Common value token */ + "AutoDelete", // 0x31 /* Common value token */ /* WV 1.2 */ + "GM", // 0x32 /* Common value token */ /* WV 1.2 */ + "Validity", // 0x33 /* Common value token */ /* WV 1.2 */ + "ShowID", // 0x34 /* Common value token */ /* WV 1.2 */ + "GRANTED", // 0x35 /* Common value token */ /* WV 1.2 */ + "PENDING", // 0x36 /* Common value token */ /* WV 1.2 */ + null, // 0x37 + null, // 0x38 + null, // 0x39 + null, // 0x3a + null, // 0x3b + null, // 0x3c + "GROUP_ID", // 0x3d /* Access value token */ + "GROUP_NAME", // 0x3e /* Access value token */ + "GROUP_TOPIC", // 0x3f /* Access value token */ + "GROUP_USER_ID_JOINED", // 0x40 /* Access value token */ + "GROUP_USER_ID_OWNER", // 0x41 /* Access value token */ + "HTTP", // 0x42 /* Access value token */ + "SMS", // 0x43 /* Access value token */ + "STCP", // 0x44 /* Access value token */ + "SUDP", // 0x45 /* Access value token */ + "USER_ALIAS", // 0x46 /* Access value token */ + "USER_EMAIL_ADDRESS", // 0x47 /* Access value token */ + "USER_FIRST_NAME", // 0x48 /* Access value token */ + "USER_ID", // 0x49 /* Access value token */ + "USER_LAST_NAME", // 0x4a /* Access value token */ + "USER_MOBILE_NUMBER", // 0x4b /* Access value token */ + "USER_ONLINE_STATUS", // 0x4c /* Access value token */ + "WAPSMS", // 0x4d /* Access value token */ + "WAPUDP", // 0x4e /* Access value token */ + "WSP", // 0x4f /* Access value token */ + "GROUP_USER_ID_AUTOJOIN", // 0x50 /* Access value token */ /* WV 1.2 */ + null, // 0x51 + null, // 0x52 + null, // 0x53 + null, // 0x54 + null, // 0x55 + null, // 0x56 + null, // 0x57 + null, // 0x58 + null, // 0x59 + null, // 0x5a + "ANGRY", // 0x5b /* Presence value token */ + "ANXIOUS", // 0x5c /* Presence value token */ + "ASHAMED", // 0x5d /* Presence value token */ + "AUDIO_CALL", // 0x5e /* Presence value token */ + "AVAILABLE", // 0x5f /* Presence value token */ + "BORED", // 0x60 /* Presence value token */ + "CALL", // 0x61 /* Presence value token */ + "CLI", // 0x62 /* Presence value token */ + "COMPUTER", // 0x63 /* Presence value token */ + "DISCREET", // 0x64 /* Presence value token */ + "EMAIL", // 0x65 /* Presence value token */ + "EXCITED", // 0x66 /* Presence value token */ + "HAPPY", // 0x67 /* Presence value token */ + "IM", // 0x68 /* Presence value token */ + "IM_OFFLINE", // 0x69 /* Presence value token */ + "IM_ONLINE", // 0x6a /* Presence value token */ + "IN_LOVE", // 0x6b /* Presence value token */ + "INVINCIBLE", // 0x6c /* Presence value token */ + "JEALOUS", // 0x6d /* Presence value token */ + "MMS", // 0x6e /* Presence value token */ + "MOBILE_PHONE", // 0x6f /* Presence value token */ + "NOT_AVAILABLE", // 0x70 /* Presence value token */ + "OTHER", // 0x71 /* Presence value token */ + "PDA", // 0x72 /* Presence value token */ + "SAD", // 0x73 /* Presence value token */ + "SLEEPY", // 0x74 /* Presence value token */ + "SMS", // 0x75 /* Presence value token */ + "VIDEO_CALL", // 0x76 /* Presence value token */ + "VIDEO_STREAM", // 0x77 /* Presence value token */ + }; + + +} diff --git a/xml/src/main/java/org/w3c/dom/Attr.java b/xml/src/main/java/org/w3c/dom/Attr.java new file mode 100644 index 0000000..3bfde52 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/Attr.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * The <code>Attr</code> interface represents an attribute in an + * <code>Element</code> object. Typically the allowable values for the + * attribute are defined in a document type definition. + * <p><code>Attr</code> objects inherit the <code>Node</code> interface, but + * since they are not actually child nodes of the element they describe, the + * DOM does not consider them part of the document tree. Thus, the + * <code>Node</code> attributes <code>parentNode</code>, + * <code>previousSibling</code>, and <code>nextSibling</code> have a + * <code>null</code> value for <code>Attr</code> objects. The DOM takes the + * view that attributes are properties of elements rather than having a + * separate identity from the elements they are associated with; this should + * make it more efficient to implement such features as default attributes + * associated with all elements of a given type. Furthermore, + * <code>Attr</code> nodes may not be immediate children of a + * <code>DocumentFragment</code>. However, they can be associated with + * <code>Element</code> nodes contained within a + * <code>DocumentFragment</code>. In short, users and implementors of the + * DOM need to be aware that <code>Attr</code> nodes have some things in + * common with other objects inheriting the <code>Node</code> interface, but + * they also are quite distinct. + * <p> The attribute's effective value is determined as follows: if this + * attribute has been explicitly assigned any value, that value is the + * attribute's effective value; otherwise, if there is a declaration for + * this attribute, and that declaration includes a default value, then that + * default value is the attribute's effective value; otherwise, the + * attribute does not exist on this element in the structure model until it + * has been explicitly added. Note that the <code>nodeValue</code> attribute + * on the <code>Attr</code> instance can also be used to retrieve the string + * version of the attribute's value(s). + * <p>In XML, where the value of an attribute can contain entity references, + * the child nodes of the <code>Attr</code> node may be either + * <code>Text</code> or <code>EntityReference</code> nodes (when these are + * in use; see the description of <code>EntityReference</code> for + * discussion). Because the DOM Core is not aware of attribute types, it + * treats all attribute values as simple strings, even if the DTD or schema + * declares them as having tokenized types. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface Attr extends Node { + /** + * Returns the name of this attribute. + * + * @return the name of the attribute. + */ + public String getName(); + + /** + * If this attribute was explicitly given a value in the original + * document, this is <code>true</code>; otherwise, it is + * <code>false</code>. Note that the implementation is in charge of this + * attribute, not the user. If the user changes the value of the + * attribute (even if it ends up having the same value as the default + * value) then the <code>specified</code> flag is automatically flipped + * to <code>true</code>. To re-specify the attribute as the default + * value from the DTD, the user must delete the attribute. The + * implementation will then make a new attribute available with + * <code>specified</code> set to <code>false</code> and the default + * value (if one exists). + * <br>In summary: If the attribute has an assigned value in the document + * then <code>specified</code> is <code>true</code>, and the value is + * the assigned value. If the attribute has no assigned value in the + * document and has a default value in the DTD, then + * <code>specified</code> is <code>false</code>, and the value is the + * default value in the DTD. If the attribute has no assigned value in + * the document and has a value of #IMPLIED in the DTD, then the + * attribute does not appear in the structure model of the document. If + * the <code>ownerElement</code> attribute is <code>null</code> (i.e. + * because it was just created or was set to <code>null</code> by the + * various removal and cloning operations) <code>specified</code> is + * <code>true</code>. + * + * @return <code>true</code> if the attribute was specified, + * <code>false</false> otherwise. + */ + public boolean getSpecified(); + + /** + * Returns the value of the attribute is returned as a string. + * Character and general entity references are replaced with their + * values. See also the method <code>getAttribute</code> on the + * <code>Element</code> interface. + * + * @return the attribute value as a string. + */ + public String getValue(); + + /** + * Sets the value of the attribute. This creates a <code>Text</code> node + * with the unparsed contents of the string. I.e. any characters that an + * XML processor would recognize as markup are instead treated as literal + * text. See also the method <code>setAttribute</code> on the + * <code>Element</code> + * interface. + * + * @param value the new attribute value. + * + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + */ + public void setValue(String value) + throws DOMException; + + /** + * The <code>Element</code> node this attribute is attached to or + * <code>null</code> if this attribute is not in use. + * + * @return the owner <code>Element</element>, or <code>null</code> is the + * attribute is unused. + * + * @since DOM Level 2 + */ + public Element getOwnerElement(); + +} diff --git a/xml/src/main/java/org/w3c/dom/CDATASection.java b/xml/src/main/java/org/w3c/dom/CDATASection.java new file mode 100644 index 0000000..9e74734 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/CDATASection.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +/** + * CDATA sections are used to escape blocks of text containing characters that + * would otherwise be regarded as markup. The only delimiter that is + * recognized in a CDATA section is the "]]>" string that ends the CDATA + * section. CDATA sections cannot be nested. Their primary purpose is for + * including material such as XML fragments, without needing to escape all + * the delimiters. + * <p>The <code>DOMString</code> attribute of the <code>Text</code> node holds + * the text that is contained by the CDATA section. Note that this may + * contain characters that need to be escaped outside of CDATA sections and + * that, depending on the character encoding ("charset") chosen for + * serialization, it may be impossible to write out some characters as part + * of a CDATA section. + * <p> The <code>CDATASection</code> interface inherits from the + * <code>CharacterData</code> interface through the <code>Text</code> + * interface. Adjacent <code>CDATASection</code> nodes are not merged by use + * of the <code>normalize</code> method of the <code>Node</code> interface. + * Because no markup is recognized within a <code>CDATASection</code>, + * character numeric references cannot be used as an escape mechanism when + * serializing. Therefore, action needs to be taken when serializing a + * <code>CDATASection</code> with a character encoding where some of the + * contained characters cannot be represented. Failure to do so would not + * produce well-formed XML.One potential solution in the serialization + * process is to end the CDATA section before the character, output the + * character using a character reference or entity reference, and open a new + * CDATA section for any further characters in the text node. Note, however, + * that some code conversion libraries at the time of writing do not return + * an error or exception when a character is missing from the encoding, + * making the task of ensuring that data is not corrupted on serialization + * more difficult. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface CDATASection extends Text { +} diff --git a/xml/src/main/java/org/w3c/dom/CharacterData.java b/xml/src/main/java/org/w3c/dom/CharacterData.java new file mode 100644 index 0000000..47386e9 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/CharacterData.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +// BEGIN android-note +// Cleaned up @param tags that seemed to be missing spaces between +// the parameter name and the start of the description. +// END android-note + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * The <code>CharacterData</code> interface extends Node with a set of + * attributes and methods for accessing character data in the DOM. For + * clarity this set is defined here rather than on each object that uses + * these attributes and methods. No DOM objects correspond directly to + * <code>CharacterData</code>, though <code>Text</code> and others do + * inherit the interface from it. All <code>offsets</code> in this interface + * start from <code>0</code>. + * <p>As explained in the <code>DOMString</code> interface, text strings in + * the DOM are represented in UTF-16, i.e. as a sequence of 16-bit units. In + * the following, the term 16-bit units is used whenever necessary to + * indicate that indexing on CharacterData is done in 16-bit units. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface CharacterData extends Node { + /** + * Returns the character data of the node that implements this interface. + * The DOM implementation may not put arbitrary limits on the amount of data + * that may be stored in a <code>CharacterData</code> node. However, + * implementation limits may mean that the entirety of a node's data may + * not fit into a single <code>DOMString</code>. In such cases, the user + * may call <code>substringData</code> to retrieve the data in + * appropriately sized pieces. + * + * @return the character data as a string. + * + * @exception DOMException + * DOMSTRING_SIZE_ERR: Raised when it would return more characters than + * fit in a <code>DOMString</code> variable on the implementation + * platform. + */ + public String getData() + throws DOMException; + /** + * Sets the character data of the node that implements this interface. The + * DOM implementation may not put arbitrary limits on the amount of data + * that may be stored in a <code>CharacterData</code> node. However, + * implementation limits may mean that the entirety of a node's data may + * not fit into a single <code>DOMString</code>. In such cases, the user + * may call <code>substringData</code> to retrieve the data in + * appropriately sized pieces. + * + * @param data the new character data. + * + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + */ + public void setData(String data) + throws DOMException; + + /** + * The number of 16-bit units that are available through <code>data</code> + * and the <code>substringData</code> method below. This may have the + * value zero, i.e., <code>CharacterData</code> nodes may be empty. + * + * @return the length in characters. + */ + public int getLength(); + + /** + * Extracts a range of data from the node. + * @param offset Start offset of substring to extract. + * @param count The number of 16-bit units to extract. + * @return The specified substring. If the sum of <code>offset</code> and + * <code>count</code> exceeds the <code>length</code>, then all 16-bit + * units to the end of the data are returned. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is + * negative or greater than the number of 16-bit units in + * <code>data</code>, or if the specified <code>count</code> is + * negative. + * <br>DOMSTRING_SIZE_ERR: Raised if the specified range of text does + * not fit into a <code>DOMString</code>. + */ + public String substringData(int offset, + int count) + throws DOMException; + + /** + * Append the string to the end of the character data of the node. Upon + * success, <code>data</code> provides access to the concatenation of + * <code>data</code> and the <code>DOMString</code> specified. + * @param arg The <code>DOMString</code> to append. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + */ + public void appendData(String arg) + throws DOMException; + + /** + * Insert a string at the specified 16-bit unit offset. + * @param offset The character offset at which to insert. + * @param arg The <code>DOMString</code> to insert. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is + * negative or greater than the number of 16-bit units in + * <code>data</code>. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + */ + public void insertData(int offset, + String arg) + throws DOMException; + + /** + * Remove a range of 16-bit units from the node. Upon success, + * <code>data</code> and <code>length</code> reflect the change. + * @param offset The offset from which to start removing. + * @param count The number of 16-bit units to delete. If the sum of + * <code>offset</code> and <code>count</code> exceeds + * <code>length</code> then all 16-bit units from <code>offset</code> + * to the end of the data are deleted. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is + * negative or greater than the number of 16-bit units in + * <code>data</code>, or if the specified <code>count</code> is + * negative. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + */ + public void deleteData(int offset, + int count) + throws DOMException; + + /** + * Replace the characters starting at the specified 16-bit unit offset + * with the specified string. + * @param offset The offset from which to start replacing. + * @param count The number of 16-bit units to replace. If the sum of + * <code>offset</code> and <code>count</code> exceeds + * <code>length</code>, then all 16-bit units to the end of the data + * are replaced; (i.e., the effect is the same as a <code>remove</code> + * method call with the same range, followed by an <code>append</code> + * method invocation). + * @param arg The <code>DOMString</code> with which the range must be + * replaced. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is + * negative or greater than the number of 16-bit units in + * <code>data</code>, or if the specified <code>count</code> is + * negative. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + */ + public void replaceData(int offset, + int count, + String arg) + throws DOMException; + +} diff --git a/xml/src/main/java/org/w3c/dom/Comment.java b/xml/src/main/java/org/w3c/dom/Comment.java new file mode 100644 index 0000000..1097921 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/Comment.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +/** + * This interface inherits from <code>CharacterData</code> and represents the + * content of a comment, i.e., all the characters between the starting ' + * <code><!--</code>' and ending '<code>--></code>'. Note that this is + * the definition of a comment in XML, and, in practice, HTML, although some + * HTML tools may implement the full SGML comment structure. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface Comment extends CharacterData { +} diff --git a/xml/src/main/java/org/w3c/dom/DOMException.java b/xml/src/main/java/org/w3c/dom/DOMException.java new file mode 100644 index 0000000..76bac3c --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/DOMException.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * DOM operations only raise exceptions in "exceptional" circumstances, i.e., + * when an operation is impossible to perform (either for logical reasons, + * because data is lost, or because the implementation has become unstable). + * In general, DOM methods return specific error values in ordinary + * processing situations, such as out-of-bound errors when using + * <code>NodeList</code>. + * <p>Implementations should raise other exceptions under other circumstances. + * For example, implementations should raise an implementation-dependent + * exception if a <code>null</code> argument is passed. + * <p>Some languages and object systems do not support the concept of + * exceptions. For such systems, error conditions may be indicated using + * native error reporting mechanisms. For some bindings, for example, + * methods may return error codes similar to those listed in the + * corresponding method descriptions. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public class DOMException extends RuntimeException { + /** + * Creates a new <code>DOMException</code> with the given error code and + * human-readable message. + * @param code the error code. + * @param message the human-readable message. + */ + public DOMException(short code, String message) { + super(message); + this.code = code; + } + /** + * Holds the error code of the <code>DOMException</code>. + */ + public short code; + // ExceptionCode + /** + * If index or size is negative, or greater than the allowed value + */ + public static final short INDEX_SIZE_ERR = 1; + /** + * If the specified range of text does not fit into a DOMString + */ + public static final short DOMSTRING_SIZE_ERR = 2; + /** + * If any node is inserted somewhere it doesn't belong + */ + public static final short HIERARCHY_REQUEST_ERR = 3; + /** + * If a node is used in a different document than the one that created it + * (that doesn't support it) + */ + public static final short WRONG_DOCUMENT_ERR = 4; + /** + * If an invalid or illegal character is specified, such as in a name. See + * production 2 in the XML specification for the definition of a legal + * character, and production 5 for the definition of a legal name + * character. + */ + public static final short INVALID_CHARACTER_ERR = 5; + /** + * If data is specified for a node which does not support data + */ + public static final short NO_DATA_ALLOWED_ERR = 6; + /** + * If an attempt is made to modify an object where modifications are not + * allowed + */ + public static final short NO_MODIFICATION_ALLOWED_ERR = 7; + /** + * If an attempt is made to reference a node in a context where it does + * not exist + */ + public static final short NOT_FOUND_ERR = 8; + /** + * If the implementation does not support the requested type of object or + * operation. + */ + public static final short NOT_SUPPORTED_ERR = 9; + /** + * If an attempt is made to add an attribute that is already in use + * elsewhere + */ + public static final short INUSE_ATTRIBUTE_ERR = 10; + /** + * If an attempt is made to use an object that is not, or is no longer, + * usable. + * @since DOM Level 2 + */ + public static final short INVALID_STATE_ERR = 11; + /** + * If an invalid or illegal string is specified. + * @since DOM Level 2 + */ + public static final short SYNTAX_ERR = 12; + /** + * If an attempt is made to modify the type of the underlying object. + * @since DOM Level 2 + */ + public static final short INVALID_MODIFICATION_ERR = 13; + /** + * If an attempt is made to create or change an object in a way which is + * incorrect with regard to namespaces. + * @since DOM Level 2 + */ + public static final short NAMESPACE_ERR = 14; + /** + * If a parameter or an operation is not supported by the underlying + * object. + * @since DOM Level 2 + */ + public static final short INVALID_ACCESS_ERR = 15; + +} diff --git a/xml/src/main/java/org/w3c/dom/DOMImplementation.java b/xml/src/main/java/org/w3c/dom/DOMImplementation.java new file mode 100644 index 0000000..dcb19c9 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/DOMImplementation.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +// BEGIN android-note +// Cleaned up @param tags that seemed to be missing spaces between +// the parameter name and the start of the description. +// END android-note + +/** + * The <code>DOMImplementation</code> interface provides a number of methods + * for performing operations that are independent of any particular instance + * of the document object model. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface DOMImplementation { + /** + * Test if the DOM implementation implements a specific feature. + * @param feature The name of the feature to test (case-insensitive). The + * values used by DOM features are defined throughout the DOM Level 2 + * specifications and listed in the section. The name must be an XML + * name. To avoid possible conflicts, as a convention, names referring + * to features defined outside the DOM specification should be made + * unique by reversing the name of the Internet domain name of the + * person (or the organization that the person belongs to) who defines + * the feature, component by component, and using this as a prefix. + * For instance, the W3C SVG Working Group defines the feature + * "org.w3c.dom.svg". + * @param version This is the version number of the feature to test. In + * Level 2, the string can be either "2.0" or "1.0". If the version is + * not specified, supporting any version of the feature causes the + * method to return <code>true</code>. + * @return <code>true</code> if the feature is implemented in the + * specified version, <code>false</code> otherwise. + */ + public boolean hasFeature(String feature, + String version); + + /** + * Creates an empty <code>DocumentType</code> node. Entity declarations + * and notations are not made available. Entity reference expansions and + * default attribute additions do not occur. It is expected that a + * future version of the DOM will provide a way for populating a + * <code>DocumentType</code>. + * <br>HTML-only DOM implementations do not need to implement this method. + * @param qualifiedName The qualified name of the document type to be + * created. + * @param publicId The external subset public identifier. + * @param systemId The external subset system identifier. + * @return A new <code>DocumentType</code> node with + * <code>Node.ownerDocument</code> set to <code>null</code>. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character. + * <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is + * malformed. + * @since DOM Level 2 + */ + public DocumentType createDocumentType(String qualifiedName, + String publicId, + String systemId) + throws DOMException; + + /** + * Creates an XML <code>Document</code> object of the specified type with + * its document element. HTML-only DOM implementations do not need to + * implement this method. + * @param namespaceURI The namespace URI of the document element to create. + * @param qualifiedName The qualified name of the document element to be + * created. + * @param doctype The type of document to be created or <code>null</code>. + * When <code>doctype</code> is not <code>null</code>, its + * <code>Node.ownerDocument</code> attribute is set to the document + * being created. + * @return A new <code>Document</code> object. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character. + * <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is + * malformed, if the <code>qualifiedName</code> has a prefix and the + * <code>namespaceURI</code> is <code>null</code>, or if the + * <code>qualifiedName</code> has a prefix that is "xml" and the + * <code>namespaceURI</code> is different from " + * http://www.w3.org/XML/1998/namespace" . + * <br>WRONG_DOCUMENT_ERR: Raised if <code>doctype</code> has already + * been used with a different document or was created from a different + * implementation. + * @since DOM Level 2 + */ + public Document createDocument(String namespaceURI, + String qualifiedName, + DocumentType doctype) + throws DOMException; + +} diff --git a/xml/src/main/java/org/w3c/dom/Document.java b/xml/src/main/java/org/w3c/dom/Document.java new file mode 100644 index 0000000..3beddaa --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/Document.java @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +// BEGIN android-note +// Cleaned up @param tags that seemed to be missing spaces between +// the parameter name and the start of the description. +// END android-note + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * The <code>Document</code> interface represents the entire HTML or XML + * document. Conceptually, it is the root of the document tree, and provides + * the primary access to the document's data. + * <p>Since elements, text nodes, comments, processing instructions, etc. + * cannot exist outside the context of a <code>Document</code>, the + * <code>Document</code> interface also contains the factory methods needed + * to create these objects. The <code>Node</code> objects created have a + * <code>ownerDocument</code> attribute which associates them with the + * <code>Document</code> within whose context they were created. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface Document extends Node { + /** + * The Document Type Declaration (see <code>DocumentType</code>) + * associated with this document. For HTML documents as well as XML + * documents without a document type declaration this returns + * <code>null</code>. The DOM Level 2 does not support editing the + * Document Type Declaration. <code>docType</code> cannot be altered in + * any way, including through the use of methods inherited from the + * <code>Node</code> interface, such as <code>insertNode</code> or + * <code>removeNode</code>. + * + * @return the Document Type Declaration associated with this document, if + * any. + */ + public DocumentType getDoctype(); + + /** + * The <code>DOMImplementation</code> object that handles this document. A + * DOM application may use objects from multiple implementations. + * + * @return <code>DOMImplementation</code> object that handles this document. + */ + public DOMImplementation getImplementation(); + + /** + * This is a convenience attribute that allows direct access to the child + * node that is the root element of the document. For HTML documents, + * this is the element with the tagName "HTML". + * + * @return the root element of this document. + */ + public Element getDocumentElement(); + + /** + * Creates an element of the type specified. Note that the instance + * returned implements the <code>Element</code> interface, so attributes + * can be specified directly on the returned object. + * <br>In addition, if there are known attributes with default values, + * <code>Attr</code> nodes representing them are automatically created + * and attached to the element. + * <br>To create an element with a qualified name and namespace URI, use + * the <code>createElementNS</code> method. + * @param tagName The name of the element type to instantiate. For XML, + * this is case-sensitive. For HTML, the <code>tagName</code> + * parameter may be provided in any case, but it must be mapped to the + * canonical uppercase form by the DOM implementation. + * @return A new <code>Element</code> object with the + * <code>nodeName</code> attribute set to <code>tagName</code>, and + * <code>localName</code>, <code>prefix</code>, and + * <code>namespaceURI</code> set to <code>null</code>. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified name contains an + * illegal character. + */ + public Element createElement(String tagName) + throws DOMException; + + /** + * Creates an empty <code>DocumentFragment</code> object. + * @return A new <code>DocumentFragment</code>. + */ + public DocumentFragment createDocumentFragment(); + + /** + * Creates a <code>Text</code> node given the specified string. + * @param data The data for the node. + * @return The new <code>Text</code> object. + */ + public Text createTextNode(String data); + + /** + * Creates a <code>Comment</code> node given the specified string. + * @param data The data for the node. + * @return The new <code>Comment</code> object. + */ + public Comment createComment(String data); + + /** + * Creates a <code>CDATASection</code> node whose value is the specified + * string. + * @param data The data for the <code>CDATASection</code> contents. + * @return The new <code>CDATASection</code> object. + * @exception DOMException + * NOT_SUPPORTED_ERR: Raised if this document is an HTML document. + */ + public CDATASection createCDATASection(String data) + throws DOMException; + + /** + * Creates a <code>ProcessingInstruction</code> node given the specified + * name and data strings. + * @param target The target part of the processing instruction. + * @param data The data for the node. + * @return The new <code>ProcessingInstruction</code> object. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified target contains an + * illegal character. + * <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document. + */ + public ProcessingInstruction createProcessingInstruction(String target, + String data) + throws DOMException; + + /** + * Creates an <code>Attr</code> of the given name. Note that the + * <code>Attr</code> instance can then be set on an <code>Element</code> + * using the <code>setAttributeNode</code> method. + * <br>To create an attribute with a qualified name and namespace URI, use + * the <code>createAttributeNS</code> method. + * @param name The name of the attribute. + * @return A new <code>Attr</code> object with the <code>nodeName</code> + * attribute set to <code>name</code>, and <code>localName</code>, + * <code>prefix</code>, and <code>namespaceURI</code> set to + * <code>null</code>. The value of the attribute is the empty string. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified name contains an + * illegal character. + */ + public Attr createAttribute(String name) + throws DOMException; + + /** + * Creates an <code>EntityReference</code> object. In addition, if the + * referenced entity is known, the child list of the + * <code>EntityReference</code> node is made the same as that of the + * corresponding <code>Entity</code> node.If any descendant of the + * <code>Entity</code> node has an unbound namespace prefix, the + * corresponding descendant of the created <code>EntityReference</code> + * node is also unbound; (its <code>namespaceURI</code> is + * <code>null</code>). The DOM Level 2 does not support any mechanism to + * resolve namespace prefixes. + * @param name The name of the entity to reference. + * @return The new <code>EntityReference</code> object. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified name contains an + * illegal character. + * <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document. + */ + public EntityReference createEntityReference(String name) + throws DOMException; + + /** + * Returns a <code>NodeList</code> of all the <code>Elements</code> with a + * given tag name in the order in which they are encountered in a + * preorder traversal of the <code>Document</code> tree. + * @param tagname The name of the tag to match on. The special value "*" + * matches all tags. + * @return A new <code>NodeList</code> object containing all the matched + * <code>Elements</code>. + */ + public NodeList getElementsByTagName(String tagname); + + /** + * Imports a node from another document to this document. The returned + * node has no parent; (<code>parentNode</code> is <code>null</code>). + * The source node is not altered or removed from the original document; + * this method creates a new copy of the source node. + * <br>For all nodes, importing a node creates a node object owned by the + * importing document, with attribute values identical to the source + * node's <code>nodeName</code> and <code>nodeType</code>, plus the + * attributes related to namespaces (<code>prefix</code>, + * <code>localName</code>, and <code>namespaceURI</code>). As in the + * <code>cloneNode</code> operation on a <code>Node</code>, the source + * node is not altered. + * <br>Additional information is copied as appropriate to the + * <code>nodeType</code>, attempting to mirror the behavior expected if + * a fragment of XML or HTML source was copied from one document to + * another, recognizing that the two documents may have different DTDs + * in the XML case. The following list describes the specifics for each + * type of node. + * <dl> + * <dt>ATTRIBUTE_NODE</dt> + * <dd>The <code>ownerElement</code> attribute + * is set to <code>null</code> and the <code>specified</code> flag is + * set to <code>true</code> on the generated <code>Attr</code>. The + * descendants of the source <code>Attr</code> are recursively imported + * and the resulting nodes reassembled to form the corresponding subtree. + * Note that the <code>deep</code> parameter has no effect on + * <code>Attr</code> nodes; they always carry their children with them + * when imported.</dd> + * <dt>DOCUMENT_FRAGMENT_NODE</dt> + * <dd>If the <code>deep</code> option + * was set to <code>true</code>, the descendants of the source element + * are recursively imported and the resulting nodes reassembled to form + * the corresponding subtree. Otherwise, this simply generates an empty + * <code>DocumentFragment</code>.</dd> + * <dt>DOCUMENT_NODE</dt> + * <dd><code>Document</code> + * nodes cannot be imported.</dd> + * <dt>DOCUMENT_TYPE_NODE</dt> + * <dd><code>DocumentType</code> + * nodes cannot be imported.</dd> + * <dt>ELEMENT_NODE</dt> + * <dd>Specified attribute nodes of the + * source element are imported, and the generated <code>Attr</code> + * nodes are attached to the generated <code>Element</code>. Default + * attributes are not copied, though if the document being imported into + * defines default attributes for this element name, those are assigned. + * If the <code>importNode</code> <code>deep</code> parameter was set to + * <code>true</code>, the descendants of the source element are + * recursively imported and the resulting nodes reassembled to form the + * corresponding subtree.</dd> + * <dt>ENTITY_NODE</dt> + * <dd><code>Entity</code> nodes can be + * imported, however in the current release of the DOM the + * <code>DocumentType</code> is readonly. Ability to add these imported + * nodes to a <code>DocumentType</code> will be considered for addition + * to a future release of the DOM.On import, the <code>publicId</code>, + * <code>systemId</code>, and <code>notationName</code> attributes are + * copied. If a <code>deep</code> import is requested, the descendants + * of the the source <code>Entity</code> are recursively imported and + * the resulting nodes reassembled to form the corresponding subtree.</dd> + * <dt> + * ENTITY_REFERENCE_NODE</dt> + * <dd>Only the <code>EntityReference</code> itself is + * copied, even if a <code>deep</code> import is requested, since the + * source and destination documents might have defined the entity + * differently. If the document being imported into provides a + * definition for this entity name, its value is assigned.</dd> + * <dt>NOTATION_NODE</dt> + * <dd> + * <code>Notation</code> nodes can be imported, however in the current + * release of the DOM the <code>DocumentType</code> is readonly. Ability + * to add these imported nodes to a <code>DocumentType</code> will be + * considered for addition to a future release of the DOM.On import, the + * <code>publicId</code> and <code>systemId</code> attributes are copied. + * Note that the <code>deep</code> parameter has no effect on + * <code>Notation</code> nodes since they never have any children.</dd> + * <dt> + * PROCESSING_INSTRUCTION_NODE</dt> + * <dd>The imported node copies its + * <code>target</code> and <code>data</code> values from those of the + * source node.</dd> + * <dt>TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE</dt> + * <dd>These three + * types of nodes inheriting from <code>CharacterData</code> copy their + * <code>data</code> and <code>length</code> attributes from those of + * the source node.</dd> + * + * @param importedNode The node to import. + * @param deep If <code>true</code>, recursively import the subtree under + * the specified node; if <code>false</code>, import only the node + * itself, as explained above. This has no effect on <code>Attr</code> + * , <code>EntityReference</code>, and <code>Notation</code> nodes. + * @return The imported node that belongs to this <code>Document</code>. + * @exception DOMException + * NOT_SUPPORTED_ERR: Raised if the type of node being imported is not + * supported. + * @since DOM Level 2 + */ + public Node importNode(Node importedNode, + boolean deep) + throws DOMException; + + /** + * Creates an element of the given qualified name and namespace URI. + * HTML-only DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the element to create. + * @param qualifiedName The qualified name of the element type to + * instantiate. + * @return A new <code>Element</code> object with the following + * attributes:AttributeValue<code>Node.nodeName</code> + * <code>qualifiedName</code><code>Node.namespaceURI</code> + * <code>namespaceURI</code><code>Node.prefix</code>prefix, extracted + * from <code>qualifiedName</code>, or <code>null</code> if there is + * no prefix<code>Node.localName</code>local name, extracted from + * <code>qualifiedName</code><code>Element.tagName</code> + * <code>qualifiedName</code> + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character. + * <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is + * malformed, if the <code>qualifiedName</code> has a prefix and the + * <code>namespaceURI</code> is <code>null</code>, or if the + * <code>qualifiedName</code> has a prefix that is "xml" and the + * <code>namespaceURI</code> is different from " + * http://www.w3.org/XML/1998/namespace" . + * @since DOM Level 2 + */ + public Element createElementNS(String namespaceURI, + String qualifiedName) + throws DOMException; + + /** + * Creates an attribute of the given qualified name and namespace URI. + * HTML-only DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the attribute to create. + * @param qualifiedName The qualified name of the attribute to instantiate. + * @return A new <code>Attr</code> object with the following attributes: + * AttributeValue<code>Node.nodeName</code>qualifiedName + * <code>Node.namespaceURI</code><code>namespaceURI</code> + * <code>Node.prefix</code>prefix, extracted from + * <code>qualifiedName</code>, or <code>null</code> if there is no + * prefix<code>Node.localName</code>local name, extracted from + * <code>qualifiedName</code><code>Attr.name</code> + * <code>qualifiedName</code><code>Node.nodeValue</code>the empty + * string + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character. + * <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is + * malformed, if the <code>qualifiedName</code> has a prefix and the + * <code>namespaceURI</code> is <code>null</code>, if the + * <code>qualifiedName</code> has a prefix that is "xml" and the + * <code>namespaceURI</code> is different from " + * http://www.w3.org/XML/1998/namespace", or if the + * <code>qualifiedName</code> is "xmlns" and the + * <code>namespaceURI</code> is different from " + * http://www.w3.org/2000/xmlns/". + * @since DOM Level 2 + */ + public Attr createAttributeNS(String namespaceURI, + String qualifiedName) + throws DOMException; + + /** + * Returns a <code>NodeList</code> of all the <code>Elements</code> with a + * given local name and namespace URI in the order in which they are + * encountered in a preorder traversal of the <code>Document</code> tree. + * @param namespaceURI The namespace URI of the elements to match on. The + * special value "*" matches all namespaces. + * @param localName The local name of the elements to match on. The + * special value "*" matches all local names. + * @return A new <code>NodeList</code> object containing all the matched + * <code>Elements</code>. + * @since DOM Level 2 + */ + public NodeList getElementsByTagNameNS(String namespaceURI, + String localName); + + /** + * Returns the <code>Element</code> whose <code>ID</code> is given by + * <code>elementId</code>. If no such element exists, returns + * <code>null</code>. Behavior is not defined if more than one element + * has this <code>ID</code>. The DOM implementation must have + * information that says which attributes are of type ID. Attributes + * with the name "ID" are not of type ID unless so defined. + * Implementations that do not know whether attributes are of type ID or + * not are expected to return <code>null</code>. + * @param elementId The unique <code>id</code> value for an element. + * @return The matching element. + * @since DOM Level 2 + */ + public Element getElementById(String elementId); + +} diff --git a/xml/src/main/java/org/w3c/dom/DocumentFragment.java b/xml/src/main/java/org/w3c/dom/DocumentFragment.java new file mode 100644 index 0000000..6ade30c --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/DocumentFragment.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +/** + * <code>DocumentFragment</code> is a "lightweight" or "minimal" + * <code>Document</code> object. It is very common to want to be able to + * extract a portion of a document's tree or to create a new fragment of a + * document. Imagine implementing a user command like cut or rearranging a + * document by moving fragments around. It is desirable to have an object + * which can hold such fragments and it is quite natural to use a Node for + * this purpose. While it is true that a <code>Document</code> object could + * fulfill this role, a <code>Document</code> object can potentially be a + * heavyweight object, depending on the underlying implementation. What is + * really needed for this is a very lightweight object. + * <code>DocumentFragment</code> is such an object. + * <p>Furthermore, various operations -- such as inserting nodes as children + * of another <code>Node</code> -- may take <code>DocumentFragment</code> + * objects as arguments; this results in all the child nodes of the + * <code>DocumentFragment</code> being moved to the child list of this node. + * <p>The children of a <code>DocumentFragment</code> node are zero or more + * nodes representing the tops of any sub-trees defining the structure of + * the document. <code>DocumentFragment</code> nodes do not need to be + * well-formed XML documents (although they do need to follow the rules + * imposed upon well-formed XML parsed entities, which can have multiple top + * nodes). For example, a <code>DocumentFragment</code> might have only one + * child and that child node could be a <code>Text</code> node. Such a + * structure model represents neither an HTML document nor a well-formed XML + * document. + * <p>When a <code>DocumentFragment</code> is inserted into a + * <code>Document</code> (or indeed any other <code>Node</code> that may + * take children) the children of the <code>DocumentFragment</code> and not + * the <code>DocumentFragment</code> itself are inserted into the + * <code>Node</code>. This makes the <code>DocumentFragment</code> very + * useful when the user wishes to create nodes that are siblings; the + * <code>DocumentFragment</code> acts as the parent of these nodes so that + * the user can use the standard methods from the <code>Node</code> + * interface, such as <code>insertBefore</code> and <code>appendChild</code>. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface DocumentFragment extends Node { +} diff --git a/xml/src/main/java/org/w3c/dom/DocumentType.java b/xml/src/main/java/org/w3c/dom/DocumentType.java new file mode 100644 index 0000000..685c073 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/DocumentType.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * Each <code>Document</code> has a <code>doctype</code> attribute whose value + * is either <code>null</code> or a <code>DocumentType</code> object. The + * <code>DocumentType</code> interface in the DOM Core provides an interface + * to the list of entities that are defined for the document, and little + * else because the effect of namespaces and the various XML schema efforts + * on DTD representation are not clearly understood as of this writing. + * <p>The DOM Level 2 doesn't support editing <code>DocumentType</code> nodes. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface DocumentType extends Node { + /** + * The name of DTD; i.e., the name immediately following the + * <code>DOCTYPE</code> keyword. + * + * @return the name of the DTD. + */ + public String getName(); + + /** + * A <code>NamedNodeMap</code> containing the general entities, both + * external and internal, declared in the DTD. Parameter entities are + * not contained. Duplicates are discarded. For example in: + * <pre><!DOCTYPE + * ex SYSTEM "ex.dtd" [ <!ENTITY foo "foo"> <!ENTITY bar + * "bar"> <!ENTITY bar "bar2"> <!ENTITY % baz "baz"> + * ]> <ex/></pre> + * the interface provides access to <code>foo</code> + * and the first declaration of <code>bar</code> but not the second + * declaration of <code>bar</code> or <code>baz</code>. Every node in + * this map also implements the <code>Entity</code> interface. + * <br>The DOM Level 2 does not support editing entities, therefore + * <code>entities</code> cannot be altered in any way. + * + * @return the entities declared in this DTD. + */ + public NamedNodeMap getEntities(); + + /** + * A <code>NamedNodeMap</code> containing the notations declared in the + * DTD. Duplicates are discarded. Every node in this map also implements + * the <code>Notation</code> interface. + * <br>The DOM Level 2 does not support editing notations, therefore + * <code>notations</code> cannot be altered in any way. + * + * @return the notations declared in this DTD. + */ + public NamedNodeMap getNotations(); + + /** + * The public identifier of the external subset. + * + * @return the public identifier. + * + * @since DOM Level 2 + */ + public String getPublicId(); + + /** + * The system identifier of the external subset. + * + * @return the system identifier. + * + * @since DOM Level 2 + */ + public String getSystemId(); + + /** + * The internal subset as a string. The actual content returned depends on + * how much information is available to the implementation. This may + * vary depending on various parameters, including the XML processor + * used to build the document. + * + * @return the internal subset. + * + * @since DOM Level 2 + */ + public String getInternalSubset(); + +} diff --git a/xml/src/main/java/org/w3c/dom/Element.java b/xml/src/main/java/org/w3c/dom/Element.java new file mode 100644 index 0000000..72e3478 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/Element.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +// BEGIN android-note +// Cleaned up @param tags that seemed to be missing spaces between +// the parameter name and the start of the description. +// END android-note + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * The <code>Element</code> interface represents an element in an HTML or XML + * document. Elements may have attributes associated with them; since the + * <code>Element</code> interface inherits from <code>Node</code>, the + * generic <code>Node</code> interface attribute <code>attributes</code> may + * be used to retrieve the set of all attributes for an element. There are + * methods on the <code>Element</code> interface to retrieve either an + * <code>Attr</code> object by name or an attribute value by name. In XML, + * where an attribute value may contain entity references, an + * <code>Attr</code> object should be retrieved to examine the possibly + * fairly complex sub-tree representing the attribute value. On the other + * hand, in HTML, where all attributes have simple string values, methods to + * directly access an attribute value can safely be used as a convenience.In + * DOM Level 2, the method <code>normalize</code> is inherited from the + * <code>Node</code> interface where it was moved. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface Element extends Node { + /** + * The name of the element. For example, in: + * <pre> <elementExample + * id="demo"> ... </elementExample> , </pre> + * <code>tagName</code> has + * the value <code>"elementExample"</code>. Note that this is + * case-preserving in XML, as are all of the operations of the DOM. The + * HTML DOM returns the <code>tagName</code> of an HTML element in the + * canonical uppercase form, regardless of the case in the source HTML + * document. + * + * @return the name of the element. + */ + public String getTagName(); + + /** + * Retrieves an attribute value by name. + * @param name The name of the attribute to retrieve. + * @return The <code>Attr</code> value as a string, or the empty string + * if that attribute does not have a specified or default value. + */ + public String getAttribute(String name); + + /** + * Adds a new attribute. If an attribute with that name is already present + * in the element, its value is changed to be that of the value + * parameter. This value is a simple string; it is not parsed as it is + * being set. So any markup (such as syntax to be recognized as an + * entity reference) is treated as literal text, and needs to be + * appropriately escaped by the implementation when it is written out. + * In order to assign an attribute value that contains entity + * references, the user must create an <code>Attr</code> node plus any + * <code>Text</code> and <code>EntityReference</code> nodes, build the + * appropriate subtree, and use <code>setAttributeNode</code> to assign + * it as the value of an attribute. + * <br>To set an attribute with a qualified name and namespace URI, use + * the <code>setAttributeNS</code> method. + * @param name The name of the attribute to create or alter. + * @param value Value to set in string form. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified name contains an + * illegal character. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + */ + public void setAttribute(String name, + String value) + throws DOMException; + + /** + * Removes an attribute by name. If the removed attribute is known to have + * a default value, an attribute immediately appears containing the + * default value as well as the corresponding namespace URI, local name, + * and prefix when applicable. + * <br>To remove an attribute by local name and namespace URI, use the + * <code>removeAttributeNS</code> method. + * @param name The name of the attribute to remove. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + */ + public void removeAttribute(String name) + throws DOMException; + + /** + * Retrieves an attribute node by name. + * <br>To retrieve an attribute node by qualified name and namespace URI, + * use the <code>getAttributeNodeNS</code> method. + * @param name The name (<code>nodeName</code>) of the attribute to + * retrieve. + * @return The <code>Attr</code> node with the specified name ( + * <code>nodeName</code>) or <code>null</code> if there is no such + * attribute. + */ + public Attr getAttributeNode(String name); + + /** + * Adds a new attribute node. If an attribute with that name ( + * <code>nodeName</code>) is already present in the element, it is + * replaced by the new one. + * <br>To add a new attribute node with a qualified name and namespace + * URI, use the <code>setAttributeNodeNS</code> method. + * @param newAttr The <code>Attr</code> node to add to the attribute list. + * @return If the <code>newAttr</code> attribute replaces an existing + * attribute, the replaced <code>Attr</code> node is returned, + * otherwise <code>null</code> is returned. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a + * different document than the one that created the element. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an + * attribute of another <code>Element</code> object. The DOM user must + * explicitly clone <code>Attr</code> nodes to re-use them in other + * elements. + */ + public Attr setAttributeNode(Attr newAttr) + throws DOMException; + + /** + * Removes the specified attribute node. If the removed <code>Attr</code> + * has a default value it is immediately replaced. The replacing + * attribute has the same namespace URI and local name, as well as the + * original prefix, when applicable. + * @param oldAttr The <code>Attr</code> node to remove from the attribute + * list. + * @return The <code>Attr</code> node that was removed. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * <br>NOT_FOUND_ERR: Raised if <code>oldAttr</code> is not an attribute + * of the element. + */ + public Attr removeAttributeNode(Attr oldAttr) + throws DOMException; + + /** + * Returns a <code>NodeList</code> of all descendant <code>Elements</code> + * with a given tag name, in the order in which they are encountered in + * a preorder traversal of this <code>Element</code> tree. + * @param name The name of the tag to match on. The special value "*" + * matches all tags. + * @return A list of matching <code>Element</code> nodes. + */ + public NodeList getElementsByTagName(String name); + + /** + * Retrieves an attribute value by local name and namespace URI. HTML-only + * DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the attribute to retrieve. + * @param localName The local name of the attribute to retrieve. + * @return The <code>Attr</code> value as a string, or the empty string + * if that attribute does not have a specified or default value. + * @since DOM Level 2 + */ + public String getAttributeNS(String namespaceURI, + String localName); + + /** + * Adds a new attribute. If an attribute with the same local name and + * namespace URI is already present on the element, its prefix is + * changed to be the prefix part of the <code>qualifiedName</code>, and + * its value is changed to be the <code>value</code> parameter. This + * value is a simple string; it is not parsed as it is being set. So any + * markup (such as syntax to be recognized as an entity reference) is + * treated as literal text, and needs to be appropriately escaped by the + * implementation when it is written out. In order to assign an + * attribute value that contains entity references, the user must create + * an <code>Attr</code> node plus any <code>Text</code> and + * <code>EntityReference</code> nodes, build the appropriate subtree, + * and use <code>setAttributeNodeNS</code> or + * <code>setAttributeNode</code> to assign it as the value of an + * attribute. + * <br>HTML-only DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the attribute to create or + * alter. + * @param qualifiedName The qualified name of the attribute to create or + * alter. + * @param value The value to set in string form. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified qualified name + * contains an illegal character. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is + * malformed, if the <code>qualifiedName</code> has a prefix and the + * <code>namespaceURI</code> is <code>null</code>, if the + * <code>qualifiedName</code> has a prefix that is "xml" and the + * <code>namespaceURI</code> is different from " + * http://www.w3.org/XML/1998/namespace", or if the + * <code>qualifiedName</code> is "xmlns" and the + * <code>namespaceURI</code> is different from " + * http://www.w3.org/2000/xmlns/". + * @since DOM Level 2 + */ + public void setAttributeNS(String namespaceURI, + String qualifiedName, + String value) + throws DOMException; + + /** + * Removes an attribute by local name and namespace URI. If the removed + * attribute has a default value it is immediately replaced. The + * replacing attribute has the same namespace URI and local name, as + * well as the original prefix. + * <br>HTML-only DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the attribute to remove. + * @param localName The local name of the attribute to remove. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * @since DOM Level 2 + */ + public void removeAttributeNS(String namespaceURI, + String localName) + throws DOMException; + + /** + * Retrieves an <code>Attr</code> node by local name and namespace URI. + * HTML-only DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the attribute to retrieve. + * @param localName The local name of the attribute to retrieve. + * @return The <code>Attr</code> node with the specified attribute local + * name and namespace URI or <code>null</code> if there is no such + * attribute. + * @since DOM Level 2 + */ + public Attr getAttributeNodeNS(String namespaceURI, + String localName); + + /** + * Adds a new attribute. If an attribute with that local name and that + * namespace URI is already present in the element, it is replaced by + * the new one. + * <br>HTML-only DOM implementations do not need to implement this method. + * @param newAttr The <code>Attr</code> node to add to the attribute list. + * @return If the <code>newAttr</code> attribute replaces an existing + * attribute with the same local name and namespace URI, the replaced + * <code>Attr</code> node is returned, otherwise <code>null</code> is + * returned. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a + * different document than the one that created the element. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an + * attribute of another <code>Element</code> object. The DOM user must + * explicitly clone <code>Attr</code> nodes to re-use them in other + * elements. + * @since DOM Level 2 + */ + public Attr setAttributeNodeNS(Attr newAttr) + throws DOMException; + + /** + * Returns a <code>NodeList</code> of all the descendant + * <code>Elements</code> with a given local name and namespace URI in + * the order in which they are encountered in a preorder traversal of + * this <code>Element</code> tree. + * <br>HTML-only DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the elements to match on. The + * special value "*" matches all namespaces. + * @param localName The local name of the elements to match on. The + * special value "*" matches all local names. + * @return A new <code>NodeList</code> object containing all the matched + * <code>Elements</code>. + * @since DOM Level 2 + */ + public NodeList getElementsByTagNameNS(String namespaceURI, + String localName); + + /** + * Returns <code>true</code> when an attribute with a given name is + * specified on this element or has a default value, <code>false</code> + * otherwise. + * @param name The name of the attribute to look for. + * @return <code>true</code> if an attribute with the given name is + * specified on this element or has a default value, <code>false</code> + * otherwise. + * @since DOM Level 2 + */ + public boolean hasAttribute(String name); + + /** + * Returns <code>true</code> when an attribute with a given local name and + * namespace URI is specified on this element or has a default value, + * <code>false</code> otherwise. HTML-only DOM implementations do not + * need to implement this method. + * @param namespaceURI The namespace URI of the attribute to look for. + * @param localName The local name of the attribute to look for. + * @return <code>true</code> if an attribute with the given local name + * and namespace URI is specified or has a default value on this + * element, <code>false</code> otherwise. + * @since DOM Level 2 + */ + public boolean hasAttributeNS(String namespaceURI, + String localName); + +} diff --git a/xml/src/main/java/org/w3c/dom/Entity.java b/xml/src/main/java/org/w3c/dom/Entity.java new file mode 100644 index 0000000..5b09608 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/Entity.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * This interface represents an entity, either parsed or unparsed, in an XML + * document. Note that this models the entity itself not the entity + * declaration. <code>Entity</code> declaration modeling has been left for a + * later Level of the DOM specification. + * <p>The <code>nodeName</code> attribute that is inherited from + * <code>Node</code> contains the name of the entity. + * <p>An XML processor may choose to completely expand entities before the + * structure model is passed to the DOM; in this case there will be no + * <code>EntityReference</code> nodes in the document tree. + * <p>XML does not mandate that a non-validating XML processor read and + * process entity declarations made in the external subset or declared in + * external parameter entities. This means that parsed entities declared in + * the external subset need not be expanded by some classes of applications, + * and that the replacement value of the entity may not be available. When + * the replacement value is available, the corresponding <code>Entity</code> + * node's child list represents the structure of that replacement text. + * Otherwise, the child list is empty. + * <p>The DOM Level 2 does not support editing <code>Entity</code> nodes; if a + * user wants to make changes to the contents of an <code>Entity</code>, + * every related <code>EntityReference</code> node has to be replaced in the + * structure model by a clone of the <code>Entity</code>'s contents, and + * then the desired changes must be made to each of those clones instead. + * <code>Entity</code> nodes and all their descendants are readonly. + * <p>An <code>Entity</code> node does not have any parent.If the entity + * contains an unbound namespace prefix, the <code>namespaceURI</code> of + * the corresponding node in the <code>Entity</code> node subtree is + * <code>null</code>. The same is true for <code>EntityReference</code> + * nodes that refer to this entity, when they are created using the + * <code>createEntityReference</code> method of the <code>Document</code> + * interface. The DOM Level 2 does not support any mechanism to resolve + * namespace prefixes. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface Entity extends Node { + /** + * The public identifier associated with the entity, if specified. If the + * public identifier was not specified, this is <code>null</code>. + * + * @return the public identifier of the entity or <code>null</code>, if the + * entity does not have a public identifier. + */ + public String getPublicId(); + + /** + * The system identifier associated with the entity, if specified. If the + * system identifier was not specified, this is <code>null</code>. + * + * @return the system identifier of the entity or <code>null</code>, if the + * entity does not have a system identifier. + */ + public String getSystemId(); + + /** + * For unparsed entities, the name of the notation for the entity. For + * parsed entities, this is <code>null</code>. + * + * @return the notation name of the entity or <code>null</code>, if the + * entity is parsed. + */ + public String getNotationName(); + +} diff --git a/xml/src/main/java/org/w3c/dom/EntityReference.java b/xml/src/main/java/org/w3c/dom/EntityReference.java new file mode 100644 index 0000000..ff3cf9d --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/EntityReference.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +/** + * <code>EntityReference</code> objects may be inserted into the structure + * model when an entity reference is in the source document, or when the + * user wishes to insert an entity reference. Note that character references + * and references to predefined entities are considered to be expanded by + * the HTML or XML processor so that characters are represented by their + * Unicode equivalent rather than by an entity reference. Moreover, the XML + * processor may completely expand references to entities while building the + * structure model, instead of providing <code>EntityReference</code> + * objects. If it does provide such objects, then for a given + * <code>EntityReference</code> node, it may be that there is no + * <code>Entity</code> node representing the referenced entity. If such an + * <code>Entity</code> exists, then the subtree of the + * <code>EntityReference</code> node is in general a copy of the + * <code>Entity</code> node subtree. However, this may not be true when an + * entity contains an unbound namespace prefix. In such a case, because the + * namespace prefix resolution depends on where the entity reference is, the + * descendants of the <code>EntityReference</code> node may be bound to + * different namespace URIs. + * <p>As for <code>Entity</code> nodes, <code>EntityReference</code> nodes and + * all their descendants are readonly. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface EntityReference extends Node { +} diff --git a/xml/src/main/java/org/w3c/dom/NamedNodeMap.java b/xml/src/main/java/org/w3c/dom/NamedNodeMap.java new file mode 100644 index 0000000..a6cbf09 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/NamedNodeMap.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +// BEGIN android-note +// Cleaned up @param tags that seemed to be missing spaces between +// the parameter name and the start of the description. +// END android-note + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * Objects implementing the <code>NamedNodeMap</code> interface are used to + * represent collections of nodes that can be accessed by name. Note that + * <code>NamedNodeMap</code> does not inherit from <code>NodeList</code>; + * <code>NamedNodeMaps</code> are not maintained in any particular order. + * Objects contained in an object implementing <code>NamedNodeMap</code> may + * also be accessed by an ordinal index, but this is simply to allow + * convenient enumeration of the contents of a <code>NamedNodeMap</code>, + * and does not imply that the DOM specifies an order to these Nodes. + * <p><code>NamedNodeMap</code> objects in the DOM are live. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface NamedNodeMap { + /** + * Retrieves a node specified by name. + * @param name The <code>nodeName</code> of a node to retrieve. + * @return A <code>Node</code> (of any type) with the specified + * <code>nodeName</code>, or <code>null</code> if it does not identify + * any node in this map. + */ + public Node getNamedItem(String name); + + /** + * Adds a node using its <code>nodeName</code> attribute. If a node with + * that name is already present in this map, it is replaced by the new + * one. + * <br>As the <code>nodeName</code> attribute is used to derive the name + * which the node must be stored under, multiple nodes of certain types + * (those that have a "special" string value) cannot be stored as the + * names would clash. This is seen as preferable to allowing nodes to be + * aliased. + * @param arg A node to store in this map. The node will later be + * accessible using the value of its <code>nodeName</code> attribute. + * @return If the new <code>Node</code> replaces an existing node the + * replaced <code>Node</code> is returned, otherwise <code>null</code> + * is returned. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if <code>arg</code> was created from a + * different document than the one that created this map. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. + * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>arg</code> is an + * <code>Attr</code> that is already an attribute of another + * <code>Element</code> object. The DOM user must explicitly clone + * <code>Attr</code> nodes to re-use them in other elements. + */ + public Node setNamedItem(Node arg) + throws DOMException; + + /** + * Removes a node specified by name. When this map contains the attributes + * attached to an element, if the removed attribute is known to have a + * default value, an attribute immediately appears containing the + * default value as well as the corresponding namespace URI, local name, + * and prefix when applicable. + * @param name The <code>nodeName</code> of the node to remove. + * @return The node removed from this map if a node with such a name + * exists. + * @exception DOMException + * NOT_FOUND_ERR: Raised if there is no node named <code>name</code> in + * this map. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. + */ + public Node removeNamedItem(String name) + throws DOMException; + + /** + * Returns the <code>index</code>th item in the map. If <code>index</code> + * is greater than or equal to the number of nodes in this map, this + * returns <code>null</code>. + * @param index Index into this map. + * @return The node at the <code>index</code>th position in the map, or + * <code>null</code> if that is not a valid index. + */ + public Node item(int index); + + /** + * The number of nodes in this map. The range of valid child node indices + * is <code>0</code> to <code>length-1</code> inclusive. + * + * @return the length of the map. + */ + public int getLength(); + + /** + * Retrieves a node specified by local name and namespace URI. HTML-only + * DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the node to retrieve. + * @param localName The local name of the node to retrieve. + * @return A <code>Node</code> (of any type) with the specified local + * name and namespace URI, or <code>null</code> if they do not + * identify any node in this map. + * @since DOM Level 2 + */ + public Node getNamedItemNS(String namespaceURI, + String localName); + + /** + * Adds a node using its <code>namespaceURI</code> and + * <code>localName</code>. If a node with that namespace URI and that + * local name is already present in this map, it is replaced by the new + * one. + * <br>HTML-only DOM implementations do not need to implement this method. + * @param arg A node to store in this map. The node will later be + * accessible using the value of its <code>namespaceURI</code> and + * <code>localName</code> attributes. + * @return If the new <code>Node</code> replaces an existing node the + * replaced <code>Node</code> is returned, otherwise <code>null</code> + * is returned. + * @exception DOMException + * WRONG_DOCUMENT_ERR: Raised if <code>arg</code> was created from a + * different document than the one that created this map. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. + * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>arg</code> is an + * <code>Attr</code> that is already an attribute of another + * <code>Element</code> object. The DOM user must explicitly clone + * <code>Attr</code> nodes to re-use them in other elements. + * @since DOM Level 2 + */ + public Node setNamedItemNS(Node arg) + throws DOMException; + + /** + * Removes a node specified by local name and namespace URI. A removed + * attribute may be known to have a default value when this map contains + * the attributes attached to an element, as returned by the attributes + * attribute of the <code>Node</code> interface. If so, an attribute + * immediately appears containing the default value as well as the + * corresponding namespace URI, local name, and prefix when applicable. + * <br>HTML-only DOM implementations do not need to implement this method. + * @param namespaceURI The namespace URI of the node to remove. + * @param localName The local name of the node to remove. + * @return The node removed from this map if a node with such a local + * name and namespace URI exists. + * @exception DOMException + * NOT_FOUND_ERR: Raised if there is no node with the specified + * <code>namespaceURI</code> and <code>localName</code> in this map. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. + * @since DOM Level 2 + */ + public Node removeNamedItemNS(String namespaceURI, + String localName) + throws DOMException; + +} diff --git a/xml/src/main/java/org/w3c/dom/Node.java b/xml/src/main/java/org/w3c/dom/Node.java new file mode 100644 index 0000000..c91c46d --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/Node.java @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +// BEGIN android-note +// Cleaned up @param tags that seemed to be missing spaces between +// the parameter name and the start of the description. +// END android-note + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * The <code>Node</code> interface is the primary datatype for the entire + * Document Object Model. It represents a single node in the document tree. + * While all objects implementing the <code>Node</code> interface expose + * methods for dealing with children, not all objects implementing the + * <code>Node</code> interface may have children. For example, + * <code>Text</code> nodes may not have children, and adding children to + * such nodes results in a <code>DOMException</code> being raised. + * <p>The attributes <code>nodeName</code>, <code>nodeValue</code> and + * <code>attributes</code> are included as a mechanism to get at node + * information without casting down to the specific derived interface. In + * cases where there is no obvious mapping of these attributes for a + * specific <code>nodeType</code> (e.g., <code>nodeValue</code> for an + * <code>Element</code> or <code>attributes</code> for a <code>Comment</code> + * ), this returns <code>null</code>. Note that the specialized interfaces + * may contain additional and more convenient mechanisms to get and set the + * relevant information. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface Node { + // NodeType + /** + * The node is an <code>Element</code>. + */ + public static final short ELEMENT_NODE = 1; + /** + * The node is an <code>Attr</code>. + */ + public static final short ATTRIBUTE_NODE = 2; + /** + * The node is a <code>Text</code> node. + */ + public static final short TEXT_NODE = 3; + /** + * The node is a <code>CDATASection</code>. + */ + public static final short CDATA_SECTION_NODE = 4; + /** + * The node is an <code>EntityReference</code>. + */ + public static final short ENTITY_REFERENCE_NODE = 5; + /** + * The node is an <code>Entity</code>. + */ + public static final short ENTITY_NODE = 6; + /** + * The node is a <code>ProcessingInstruction</code>. + */ + public static final short PROCESSING_INSTRUCTION_NODE = 7; + /** + * The node is a <code>Comment</code>. + */ + public static final short COMMENT_NODE = 8; + /** + * The node is a <code>Document</code>. + */ + public static final short DOCUMENT_NODE = 9; + /** + * The node is a <code>DocumentType</code>. + */ + public static final short DOCUMENT_TYPE_NODE = 10; + /** + * The node is a <code>DocumentFragment</code>. + */ + public static final short DOCUMENT_FRAGMENT_NODE = 11; + /** + * The node is a <code>Notation</code>. + */ + public static final short NOTATION_NODE = 12; + + /** + * The name of this node, depending on its type; see the table above. + * + * @return the name of the node. + */ + public String getNodeName(); + + /** + * Returns the value of this node, depending on its type; see the table + * above. + * + * @return the value of the node. + * + * @exception DOMException + * DOMSTRING_SIZE_ERR: Raised when it would return more characters than + * fit in a <code>DOMString</code> variable on the implementation + * platform. + */ + public String getNodeValue() + throws DOMException; + /** + * Sets the value of this node, depending on its type; see the table above. + * When it is defined to be <code>null</code>, setting it has no effect. + * + * @param nodeValue the new value of the node. + * + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + */ + public void setNodeValue(String nodeValue) + throws DOMException; + + /** + * A code representing the type of the underlying object, as defined above. + * + * @return the type of the node. + */ + public short getNodeType(); + + /** + * The parent of this node. All nodes, except <code>Attr</code>, + * <code>Document</code>, <code>DocumentFragment</code>, + * <code>Entity</code>, and <code>Notation</code> may have a parent. + * However, if a node has just been created and not yet added to the + * tree, or if it has been removed from the tree, this is + * <code>null</code>. + * + * @return the parent node, if any. + */ + public Node getParentNode(); + + /** + * A <code>NodeList</code> that contains all children of this node. If + * there are no children, this is a <code>NodeList</code> containing no + * nodes. + * + * @return the list of children, which may be empty. + */ + public NodeList getChildNodes(); + + /** + * The first child of this node. If there is no such node, this returns + * <code>null</code>. + * + * @return the first child of the node, if any. + */ + public Node getFirstChild(); + + /** + * The last child of this node. If there is no such node, this returns + * <code>null</code>. + * + * @return the last child of the node, if any. + */ + public Node getLastChild(); + + /** + * The node immediately preceding this node. If there is no such node, + * this returns <code>null</code>. + * + * @return the preceding node, if any. + */ + public Node getPreviousSibling(); + + /** + * The node immediately following this node. If there is no such node, + * this returns <code>null</code>. + * + * @return the following node, if any. + */ + public Node getNextSibling(); + + /** + * A <code>NamedNodeMap</code> containing the attributes of this node (if + * it is an <code>Element</code>) or <code>null</code> otherwise. + * + * @return the attributes of the node, which may be an empty map, or + * <code>null</code>, if this the node cannot have any attributes. + */ + public NamedNodeMap getAttributes(); + + /** + * The <code>Document</code> object associated with this node. This is + * also the <code>Document</code> object used to create new nodes. When + * this node is a <code>Document</code> or a <code>DocumentType</code> + * which is not used with any <code>Document</code> yet, this is + * <code>null</code>. + * + * @return the document this node belongs to, if any. + * + * @version DOM Level 2 + */ + public Document getOwnerDocument(); + + /** + * Inserts the node <code>newChild</code> before the existing child node + * <code>refChild</code>. If <code>refChild</code> is <code>null</code>, + * insert <code>newChild</code> at the end of the list of children. + * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object, + * all of its children are inserted, in the same order, before + * <code>refChild</code>. If the <code>newChild</code> is already in the + * tree, it is first removed. + * @param newChild The node to insert. + * @param refChild The reference node, i.e., the node before which the new + * node must be inserted. + * @return The node being inserted. + * @exception DOMException + * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not + * allow children of the type of the <code>newChild</code> node, or if + * the node to insert is one of this node's ancestors. + * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created + * from a different document than the one that created this node. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly or + * if the parent of the node being inserted is readonly. + * <br>NOT_FOUND_ERR: Raised if <code>refChild</code> is not a child of + * this node. + */ + public Node insertBefore(Node newChild, + Node refChild) + throws DOMException; + + /** + * Replaces the child node <code>oldChild</code> with <code>newChild</code> + * in the list of children, and returns the <code>oldChild</code> node. + * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object, + * <code>oldChild</code> is replaced by all of the + * <code>DocumentFragment</code> children, which are inserted in the + * same order. If the <code>newChild</code> is already in the tree, it + * is first removed. + * @param newChild The new node to put in the child list. + * @param oldChild The node being replaced in the list. + * @return The node replaced. + * @exception DOMException + * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not + * allow children of the type of the <code>newChild</code> node, or if + * the node to put in is one of this node's ancestors. + * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created + * from a different document than the one that created this node. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node or the parent of + * the new node is readonly. + * <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of + * this node. + */ + public Node replaceChild(Node newChild, + Node oldChild) + throws DOMException; + + /** + * Removes the child node indicated by <code>oldChild</code> from the list + * of children, and returns it. + * @param oldChild The node being removed. + * @return The node removed. + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of + * this node. + */ + public Node removeChild(Node oldChild) + throws DOMException; + + /** + * Adds the node <code>newChild</code> to the end of the list of children + * of this node. If the <code>newChild</code> is already in the tree, it + * is first removed. + * @param newChild The node to add.If it is a <code>DocumentFragment</code> + * object, the entire contents of the document fragment are moved + * into the child list of this node + * @return The node added. + * @exception DOMException + * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not + * allow children of the type of the <code>newChild</code> node, or if + * the node to append is one of this node's ancestors. + * <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created + * from a different document than the one that created this node. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + */ + public Node appendChild(Node newChild) + throws DOMException; + + /** + * Returns whether this node has any children. + * @return <code>true</code> if this node has any children, + * <code>false</code> otherwise. + */ + public boolean hasChildNodes(); + + /** + * Returns a duplicate of this node, i.e., serves as a generic copy + * constructor for nodes. The duplicate node has no parent; ( + * <code>parentNode</code> is <code>null</code>.). + * <br>Cloning an <code>Element</code> copies all attributes and their + * values, including those generated by the XML processor to represent + * defaulted attributes, but this method does not copy any text it + * contains unless it is a deep clone, since the text is contained in a + * child <code>Text</code> node. Cloning an <code>Attribute</code> + * directly, as opposed to be cloned as part of an <code>Element</code> + * cloning operation, returns a specified attribute ( + * <code>specified</code> is <code>true</code>). Cloning any other type + * of node simply returns a copy of this node. + * <br>Note that cloning an immutable subtree results in a mutable copy, + * but the children of an <code>EntityReference</code> clone are readonly + * . In addition, clones of unspecified <code>Attr</code> nodes are + * specified. And, cloning <code>Document</code>, + * <code>DocumentType</code>, <code>Entity</code>, and + * <code>Notation</code> nodes is implementation dependent. + * @param deep If <code>true</code>, recursively clone the subtree under + * the specified node; if <code>false</code>, clone only the node + * itself (and its attributes, if it is an <code>Element</code>). + * @return The duplicate node. + */ + public Node cloneNode(boolean deep); + + /** + * Puts all <code>Text</code> nodes in the full depth of the sub-tree + * underneath this <code>Node</code>, including attribute nodes, into a + * "normal" form where only structure (e.g., elements, comments, + * processing instructions, CDATA sections, and entity references) + * separates <code>Text</code> nodes, i.e., there are neither adjacent + * <code>Text</code> nodes nor empty <code>Text</code> nodes. This can + * be used to ensure that the DOM view of a document is the same as if + * it were saved and re-loaded, and is useful when operations (such as + * XPointer lookups) that depend on a particular document tree + * structure are to be used.In cases where the document contains + * <code>CDATASections</code>, the normalize operation alone may not be + * sufficient, since XPointers do not differentiate between + * <code>Text</code> nodes and <code>CDATASection</code> nodes. + * @version DOM Level 2 + */ + public void normalize(); + + /** + * Tests whether the DOM implementation implements a specific feature and + * that feature is supported by this node. + * @param feature The name of the feature to test. This is the same name + * which can be passed to the method <code>hasFeature</code> on + * <code>DOMImplementation</code>. + * @param version This is the version number of the feature to test. In + * Level 2, version 1, this is the string "2.0". If the version is not + * specified, supporting any version of the feature will cause the + * method to return <code>true</code>. + * @return Returns <code>true</code> if the specified feature is + * supported on this node, <code>false</code> otherwise. + * @since DOM Level 2 + */ + public boolean isSupported(String feature, + String version); + + /** + * The namespace URI of this node, or <code>null</code> if it is + * unspecified. + * <br>This is not a computed value that is the result of a namespace + * lookup based on an examination of the namespace declarations in + * scope. It is merely the namespace URI given at creation time. + * <br>For nodes of any type other than <code>ELEMENT_NODE</code> and + * <code>ATTRIBUTE_NODE</code> and nodes created with a DOM Level 1 + * method, such as <code>createElement</code> from the + * <code>Document</code> interface, this is always <code>null</code>.Per + * the Namespaces in XML Specification an attribute does not inherit + * its namespace from the element it is attached to. If an attribute is + * not explicitly given a namespace, it simply has no namespace. + * + * @return the namespace URI, if any. + * + * @since DOM Level 2 + */ + public String getNamespaceURI(); + + /** + * Returns the namespace prefix of this node, or <code>null</code> if it is + * unspecified. + * <br>For nodes of any type other than <code>ELEMENT_NODE</code> and + * <code>ATTRIBUTE_NODE</code> and nodes created with a DOM Level 1 + * method, such as <code>createElement</code> from the + * <code>Document</code> interface, this is always <code>null</code>. + * + * @return the namespace prefix, if any. + * + * @exception DOMException + * @since DOM Level 2 + */ + public String getPrefix(); + + /** + * Sets the namespace prefix of this node. + * <br>Note that setting this attribute, when permitted, changes the + * <code>nodeName</code> attribute, which holds the qualified name, as + * well as the <code>tagName</code> and <code>name</code> attributes of + * the <code>Element</code> and <code>Attr</code> interfaces, when + * applicable. + * <br>Note also that changing the prefix of an attribute that is known to + * have a default value, does not make a new attribute with the default + * value and the original prefix appear, since the + * <code>namespaceURI</code> and <code>localName</code> do not change. + * <br>For nodes of any type other than <code>ELEMENT_NODE</code> and + * <code>ATTRIBUTE_NODE</code> and nodes created with a DOM Level 1 + * method, such as <code>createElement</code> from the + * <code>Document</code> interface, this is always <code>null</code>. + * @exception DOMException + * INVALID_CHARACTER_ERR: Raised if the specified prefix contains an + * illegal character. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + * <br>NAMESPACE_ERR: Raised if the specified <code>prefix</code> is + * malformed, if the <code>namespaceURI</code> of this node is + * <code>null</code>, if the specified prefix is "xml" and the + * <code>namespaceURI</code> of this node is different from " + * http://www.w3.org/XML/1998/namespace", if this node is an attribute + * and the specified prefix is "xmlns" and the + * <code>namespaceURI</code> of this node is different from " + * http://www.w3.org/2000/xmlns/", or if this node is an attribute and + * the <code>qualifiedName</code> of this node is "xmlns" . + * + * @param prefix the new namespace prefix. + * + * @since DOM Level 2 + */ + public void setPrefix(String prefix) + throws DOMException; + + /** + * Returns the local part of the qualified name of this node. + * <br>For nodes of any type other than <code>ELEMENT_NODE</code> and + * <code>ATTRIBUTE_NODE</code> and nodes created with a DOM Level 1 + * method, such as <code>createElement</code> from the + * <code>Document</code> interface, this is always <code>null</code>. + * + * @return the local name, if any. + * + * @since DOM Level 2 + */ + public String getLocalName(); + + /** + * Returns whether this node (if it is an element) has any attributes. + * @return <code>true</code> if this node has any attributes, + * <code>false</code> otherwise. + * @since DOM Level 2 + */ + public boolean hasAttributes(); + +} diff --git a/xml/src/main/java/org/w3c/dom/NodeList.java b/xml/src/main/java/org/w3c/dom/NodeList.java new file mode 100644 index 0000000..0dbadda --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/NodeList.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +// BEGIN android-note +// Cleaned up @param tags that seemed to be missing spaces between +// the parameter name and the start of the description. +// END android-note + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * The <code>NodeList</code> interface provides the abstraction of an ordered + * collection of nodes, without defining or constraining how this collection + * is implemented. <code>NodeList</code> objects in the DOM are live. + * <p>The items in the <code>NodeList</code> are accessible via an integral + * index, starting from 0. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface NodeList { + /** + * Returns the <code>index</code>th item in the collection. If + * <code>index</code> is greater than or equal to the number of nodes in + * the list, this returns <code>null</code>. + * @param index Index into the collection. + * @return The node at the <code>index</code>th position in the + * <code>NodeList</code>, or <code>null</code> if that is not a valid + * index. + */ + public Node item(int index); + + /** + * The number of nodes in the list. The range of valid child node indices + * is 0 to <code>length-1</code> inclusive. + * + * @return the length of the list. + */ + public int getLength(); + +} diff --git a/xml/src/main/java/org/w3c/dom/Notation.java b/xml/src/main/java/org/w3c/dom/Notation.java new file mode 100644 index 0000000..00c702f --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/Notation.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * This interface represents a notation declared in the DTD. A notation either + * declares, by name, the format of an unparsed entity (see section 4.7 of + * the XML 1.0 specification ), or is used for formal declaration of + * processing instruction targets (see section 2.6 of the XML 1.0 + * specification ). The <code>nodeName</code> attribute inherited from + * <code>Node</code> is set to the declared name of the notation. + * <p>The DOM Level 1 does not support editing <code>Notation</code> nodes; + * they are therefore readonly. + * <p>A <code>Notation</code> node does not have any parent. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface Notation extends Node { + /** + * The public identifier of this notation. If the public identifier was + * not specified, this is <code>null</code>. + * + * @return the public identifier of this notation, if any. + */ + public String getPublicId(); + + /** + * The system identifier of this notation. If the system identifier was + * not specified, this is <code>null</code>. + * + * @return the system identifier of this notation, if any. + */ + public String getSystemId(); + +} diff --git a/xml/src/main/java/org/w3c/dom/ProcessingInstruction.java b/xml/src/main/java/org/w3c/dom/ProcessingInstruction.java new file mode 100644 index 0000000..a702aa6 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/ProcessingInstruction.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +//BEGIN android-note +//Filled some gaps in the documentation and refactored parts of the existing +//documentation to make the Doclet happy. +//END android-note + +/** + * The <code>ProcessingInstruction</code> interface represents a "processing + * instruction", used in XML as a way to keep processor-specific information + * in the text of the document. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface ProcessingInstruction extends Node { + /** + * The target of this processing instruction. XML defines this as being + * the first token following the markup that begins the processing + * instruction. + * + * @return the target of this processing instruction. + */ + public String getTarget(); + + /** + * Returns the content of this processing instruction. This is from the + * first non white space character after the target to the character + * immediately preceding the <code>?></code>. + * + * @return the data of this processing instruction. + */ + public String getData(); + + /** + * Sets the content of this processing instruction. This is from the first + * non white space character after the target to the character immediately + * preceding the <code>?></code>. + * + * @param data the new data of the processing instruction. + * + * @exception DOMException + * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + */ + public void setData(String data) + throws DOMException; + +} diff --git a/xml/src/main/java/org/w3c/dom/Text.java b/xml/src/main/java/org/w3c/dom/Text.java new file mode 100644 index 0000000..4d1746b --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/Text.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2000 World Wide Web Consortium, + * (Massachusetts Institute of Technology, Institut National de + * Recherche en Informatique et en Automatique, Keio University). All + * Rights Reserved. This program is distributed under the W3C's Software + * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + */ + +package org.w3c.dom; + +// BEGIN android-note +// Cleaned up @param tags that seemed to be missing spaces between +// the parameter name and the start of the description. +// END android-note + +/** + * The <code>Text</code> interface inherits from <code>CharacterData</code> + * and represents the textual content (termed character data in XML) of an + * <code>Element</code> or <code>Attr</code>. If there is no markup inside + * an element's content, the text is contained in a single object + * implementing the <code>Text</code> interface that is the only child of + * the element. If there is markup, it is parsed into the information items + * (elements, comments, etc.) and <code>Text</code> nodes that form the list + * of children of the element. + * <p>When a document is first made available via the DOM, there is only one + * <code>Text</code> node for each block of text. Users may create adjacent + * <code>Text</code> nodes that represent the contents of a given element + * without any intervening markup, but should be aware that there is no way + * to represent the separations between these nodes in XML or HTML, so they + * will not (in general) persist between DOM editing sessions. The + * <code>normalize()</code> method on <code>Node</code> merges any such + * adjacent <code>Text</code> objects into a single node for each block of + * text. + * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>. + */ +public interface Text extends CharacterData { + /** + * Breaks this node into two nodes at the specified <code>offset</code>, + * keeping both in the tree as siblings. After being split, this node + * will contain all the content up to the <code>offset</code> point. A + * new node of the same type, which contains all the content at and + * after the <code>offset</code> point, is returned. If the original + * node had a parent node, the new node is inserted as the next sibling + * of the original node. When the <code>offset</code> is equal to the + * length of this node, the new node has no data. + * @param offset The 16-bit unit offset at which to split, starting from + * <code>0</code>. + * @return The new node, of the same type as this node. + * @exception DOMException + * INDEX_SIZE_ERR: Raised if the specified offset is negative or greater + * than the number of 16-bit units in <code>data</code>. + * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. + */ + public Text splitText(int offset) + throws DOMException; + +} diff --git a/xml/src/main/java/org/w3c/dom/package.html b/xml/src/main/java/org/w3c/dom/package.html new file mode 100644 index 0000000..8189944 --- /dev/null +++ b/xml/src/main/java/org/w3c/dom/package.html @@ -0,0 +1,12 @@ +<html> + <body> + <p> + Provides the official W3C Java bindings for the Document Object Model, + level 2 core. XML documents returned by + {@link javax.xml.parsers.DocumentBuilder} are accessed and manipulated + through these interfaces. + </p> + + @since Android 1.0 + </body> +</html>
\ No newline at end of file diff --git a/xml/src/main/java/org/xml/sax/AttributeList.java b/xml/src/main/java/org/xml/sax/AttributeList.java new file mode 100644 index 0000000..9285eac --- /dev/null +++ b/xml/src/main/java/org/xml/sax/AttributeList.java @@ -0,0 +1,193 @@ +// SAX Attribute List Interface. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: AttributeList.java,v 1.7 2004/04/26 17:34:34 dmegginson Exp $ + +package org.xml.sax; + +/** + * Interface for an element's attribute specifications. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This is the original SAX1 interface for reporting an element's + * attributes. Unlike the new {@link org.xml.sax.Attributes Attributes} + * interface, it does not support Namespace-related information.</p> + * + * <p>When an attribute list is supplied as part of a + * {@link org.xml.sax.DocumentHandler#startElement startElement} + * event, the list will return valid results only during the + * scope of the event; once the event handler returns control + * to the parser, the attribute list is invalid. To save a + * persistent copy of the attribute list, use the SAX1 + * {@link org.xml.sax.helpers.AttributeListImpl AttributeListImpl} + * helper class.</p> + * + * <p>An attribute list includes only attributes that have been + * specified or defaulted: #IMPLIED attributes will not be included.</p> + * + * <p>There are two ways for the SAX application to obtain information + * from the AttributeList. First, it can iterate through the entire + * list:</p> + * + * <pre> + * public void startElement (String name, AttributeList atts) { + * for (int i = 0; i < atts.getLength(); i++) { + * String name = atts.getName(i); + * String type = atts.getType(i); + * String value = atts.getValue(i); + * [...] + * } + * } + * </pre> + * + * <p>(Note that the result of getLength() will be zero if there + * are no attributes.) + * + * <p>As an alternative, the application can request the value or + * type of specific attributes:</p> + * + * <pre> + * public void startElement (String name, AttributeList atts) { + * String identifier = atts.getValue("id"); + * String label = atts.getValue("label"); + * [...] + * } + * </pre> + * + * @deprecated This interface has been replaced by the SAX2 + * {@link org.xml.sax.Attributes Attributes} + * interface, which includes Namespace support. + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.DocumentHandler#startElement startElement + * @see org.xml.sax.helpers.AttributeListImpl AttributeListImpl + */ +public interface AttributeList { + + + //////////////////////////////////////////////////////////////////// + // Iteration methods. + //////////////////////////////////////////////////////////////////// + + + /** + * Return the number of attributes in this list. + * + * <p>The SAX parser may provide attributes in any + * arbitrary order, regardless of the order in which they were + * declared or specified. The number of attributes may be + * zero.</p> + * + * @return The number of attributes in the list. + */ + public abstract int getLength (); + + + /** + * Return the name of an attribute in this list (by position). + * + * <p>The names must be unique: the SAX parser shall not include the + * same attribute twice. Attributes without values (those declared + * #IMPLIED without a value specified in the start tag) will be + * omitted from the list.</p> + * + * <p>If the attribute name has a namespace prefix, the prefix + * will still be attached.</p> + * + * @param i The index of the attribute in the list (starting at 0). + * @return The name of the indexed attribute, or null + * if the index is out of range. + * @see #getLength + */ + public abstract String getName (int i); + + + /** + * Return the type of an attribute in the list (by position). + * + * <p>The attribute type is one of the strings "CDATA", "ID", + * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", + * or "NOTATION" (always in upper case).</p> + * + * <p>If the parser has not read a declaration for the attribute, + * or if the parser does not report attribute types, then it must + * return the value "CDATA" as stated in the XML 1.0 Recommentation + * (clause 3.3.3, "Attribute-Value Normalization").</p> + * + * <p>For an enumerated attribute that is not a notation, the + * parser will report the type as "NMTOKEN".</p> + * + * @param i The index of the attribute in the list (starting at 0). + * @return The attribute type as a string, or + * null if the index is out of range. + * @see #getLength + * @see #getType(java.lang.String) + */ + public abstract String getType (int i); + + + /** + * Return the value of an attribute in the list (by position). + * + * <p>If the attribute value is a list of tokens (IDREFS, + * ENTITIES, or NMTOKENS), the tokens will be concatenated + * into a single string separated by whitespace.</p> + * + * @param i The index of the attribute in the list (starting at 0). + * @return The attribute value as a string, or + * null if the index is out of range. + * @see #getLength + * @see #getValue(java.lang.String) + */ + public abstract String getValue (int i); + + + + //////////////////////////////////////////////////////////////////// + // Lookup methods. + //////////////////////////////////////////////////////////////////// + + + /** + * Return the type of an attribute in the list (by name). + * + * <p>The return value is the same as the return value for + * getType(int).</p> + * + * <p>If the attribute name has a namespace prefix in the document, + * the application must include the prefix here.</p> + * + * @param name The name of the attribute. + * @return The attribute type as a string, or null if no + * such attribute exists. + * @see #getType(int) + */ + public abstract String getType (String name); + + + /** + * Return the value of an attribute in the list (by name). + * + * <p>The return value is the same as the return value for + * getValue(int).</p> + * + * <p>If the attribute name has a namespace prefix in the document, + * the application must include the prefix here.</p> + * + * @param name the name of the attribute to return + * @return The attribute value as a string, or null if + * no such attribute exists. + * @see #getValue(int) + */ + public abstract String getValue (String name); + +} + +// end of AttributeList.java diff --git a/xml/src/main/java/org/xml/sax/Attributes.java b/xml/src/main/java/org/xml/sax/Attributes.java new file mode 100644 index 0000000..b25432d --- /dev/null +++ b/xml/src/main/java/org/xml/sax/Attributes.java @@ -0,0 +1,257 @@ +// 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.13 2004/03/18 12:28:05 dmegginson Exp $ + +package org.xml.sax; + + +/** + * Interface for a list of XML attributes. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This interface allows access to a list of attributes in + * three different ways:</p> + * + * <ol> + * <li>by attribute index;</li> + * <li>by Namespace-qualified name; or</li> + * <li>by qualified (prefixed) name.</li> + * </ol> + * + * <p>The list will not contain attributes that were declared + * #IMPLIED but not specified in the start tag. It will also not + * contain attributes used as Namespace declarations (xmlns*) unless + * the <code>http://xml.org/sax/features/namespace-prefixes</code> + * feature is set to <var>true</var> (it is <var>false</var> by + * default). + * Because SAX2 conforms to the original "Namespaces in XML" + * recommendation, it normally does not + * give namespace declaration attributes a namespace URI. + * </p> + * + * <p>Some SAX2 parsers may support using an optional feature flag + * (<code>http://xml.org/sax/features/xmlns-uris</code>) to request + * that those attributes be given URIs, conforming to a later + * backwards-incompatible revision of that recommendation. (The + * attribute's "local name" will be the prefix, or "xmlns" when + * defining a default element namespace.) For portability, handler + * code should always resolve that conflict, rather than requiring + * parsers that can change the setting of that feature flag. </p> + * + * <p>If the namespace-prefixes feature (see above) is + * <var>false</var>, access by qualified name may not be available; if + * the <code>http://xml.org/sax/features/namespaces</code> feature is + * <var>false</var>, access by Namespace-qualified names may not be + * available.</p> + * + * <p>This interface replaces the now-deprecated SAX1 {@link + * org.xml.sax.AttributeList AttributeList} interface, which does not + * contain Namespace support. In addition to Namespace support, it + * adds the <var>getIndex</var> methods (below).</p> + * + * <p>The order of attributes in the list is unspecified, and will + * vary from implementation to implementation.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.helpers.AttributesImpl + * @see org.xml.sax.ext.DeclHandler#attributeDecl + */ +public interface Attributes +{ + + + //////////////////////////////////////////////////////////////////// + // Indexed access. + //////////////////////////////////////////////////////////////////// + + + /** + * Return the number of attributes in the list. + * + * <p>Once you know the number of attributes, you can iterate + * through the list.</p> + * + * @return The number of attributes in the list. + * @see #getURI(int) + * @see #getLocalName(int) + * @see #getQName(int) + * @see #getType(int) + * @see #getValue(int) + */ + public abstract int getLength (); + + + /** + * Look up an attribute's Namespace URI by index. + * + * @param index The attribute index (zero-based). + * @return The Namespace URI, or the empty string if none + * is available, or null if the index is out of + * range. + * @see #getLength + */ + public abstract String getURI (int index); + + + /** + * Look up an attribute's local name by index. + * + * @param index The attribute index (zero-based). + * @return The local name, or the empty string if Namespace + * processing is not being performed, or null + * if the index is out of range. + * @see #getLength + */ + public abstract String getLocalName (int index); + + + /** + * Look up an attribute's XML qualified (prefixed) name by index. + * + * @param index The attribute index (zero-based). + * @return The XML qualified name, or the empty string + * if none is available, or null if the index + * is out of range. + * @see #getLength + */ + public abstract String getQName (int index); + + + /** + * Look up an attribute's type by index. + * + * <p>The attribute type is one of the strings "CDATA", "ID", + * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", + * or "NOTATION" (always in upper case).</p> + * + * <p>If the parser has not read a declaration for the attribute, + * or if the parser does not report attribute types, then it must + * return the value "CDATA" as stated in the XML 1.0 Recommendation + * (clause 3.3.3, "Attribute-Value Normalization").</p> + * + * <p>For an enumerated attribute that is not a notation, the + * parser will report the type as "NMTOKEN".</p> + * + * @param index The attribute index (zero-based). + * @return The attribute's type as a string, or null if the + * index is out of range. + * @see #getLength + */ + public abstract String getType (int index); + + + /** + * Look up an attribute's value by index. + * + * <p>If the attribute value is a list of tokens (IDREFS, + * ENTITIES, or NMTOKENS), the tokens will be concatenated + * into a single string with each token separated by a + * single space.</p> + * + * @param index The attribute index (zero-based). + * @return The attribute's value as a string, or null if the + * index is out of range. + * @see #getLength + */ + public abstract String getValue (int index); + + + + //////////////////////////////////////////////////////////////////// + // Name-based query. + //////////////////////////////////////////////////////////////////// + + + /** + * Look up the index of an attribute by Namespace name. + * + * @param uri The Namespace URI, or the empty string if + * the name has no Namespace URI. + * @param localName The attribute's local name. + * @return The index of the attribute, or -1 if it does not + * appear in the list. + */ + public int getIndex (String uri, String localName); + + + /** + * Look up the index of an attribute by XML qualified (prefixed) name. + * + * @param qName The qualified (prefixed) name. + * @return The index of the attribute, or -1 if it does not + * appear in the list. + */ + public int getIndex (String qName); + + + /** + * Look up an attribute's type by Namespace name. + * + * <p>See {@link #getType(int) getType(int)} for a description + * of the possible types.</p> + * + * @param uri The Namespace URI, or the empty String if the + * name has no Namespace URI. + * @param localName The local name of the attribute. + * @return The attribute type as a string, or null if the + * attribute is not in the list or if Namespace + * processing is not being performed. + */ + public abstract String getType (String uri, String localName); + + + /** + * Look up an attribute's type by XML qualified (prefixed) name. + * + * <p>See {@link #getType(int) getType(int)} for a description + * of the possible types.</p> + * + * @param qName The XML qualified name. + * @return The attribute type as a string, or null if the + * attribute is not in the list or if qualified names + * are not available. + */ + public abstract String getType (String qName); + + + /** + * Look up an attribute's value by Namespace name. + * + * <p>See {@link #getValue(int) getValue(int)} for a description + * of the possible values.</p> + * + * @param uri The Namespace URI, or the empty String if the + * name has no Namespace URI. + * @param localName The local name of the attribute. + * @return The attribute value as a string, or null if the + * attribute is not in the list. + */ + public abstract String getValue (String uri, String localName); + + + /** + * Look up an attribute's value by XML qualified (prefixed) name. + * + * <p>See {@link #getValue(int) getValue(int)} for a description + * of the possible values.</p> + * + * @param qName The XML qualified name. + * @return The attribute value as a string, or null if the + * attribute is not in the list or if qualified names + * are not available. + */ + public abstract String getValue (String qName); + +} + +// end of Attributes.java diff --git a/xml/src/main/java/org/xml/sax/ContentHandler.java b/xml/src/main/java/org/xml/sax/ContentHandler.java new file mode 100644 index 0000000..db66c0d --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ContentHandler.java @@ -0,0 +1,419 @@ +// 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.13 2004/04/26 17:50:49 dmegginson Exp $ + +package org.xml.sax; + + +/** + * Receive notification of the logical content of a document. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This is the main interface that most SAX applications + * implement: if the application needs to be informed of basic parsing + * events, it implements this interface and registers an instance with + * the SAX parser using the {@link org.xml.sax.XMLReader#setContentHandler + * setContentHandler} method. The parser uses the instance to report + * basic document-related events like the start and end of elements + * and character data.</p> + * + * <p>The order of events in this interface is very important, and + * mirrors the order of information in the document itself. For + * example, all of an element's content (character data, processing + * instructions, and/or subelements) will appear, in order, between + * the startElement event and the corresponding endElement event.</p> + * + * <p>This interface is similar to the now-deprecated SAX 1.0 + * DocumentHandler interface, but it adds support for Namespaces + * and for reporting skipped entities (in non-validating XML + * processors).</p> + * + * <p>Implementors should note that there is also a + * <code>ContentHandler</code> class in the <code>java.net</code> + * package; that means that it's probably a bad idea to do</p> + * + * <pre>import java.net.*; + * import org.xml.sax.*; + * </pre> + * + * <p>In fact, "import ...*" is usually a sign of sloppy programming + * anyway, so the user should consider this a feature rather than a + * bug.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1+ (sax2r3pre1) + * @see org.xml.sax.XMLReader + * @see org.xml.sax.DTDHandler + * @see org.xml.sax.ErrorHandler + */ +public interface ContentHandler +{ + + /** + * Receive an object for locating the origin of SAX document events. + * + * <p>SAX parsers are strongly encouraged (though not absolutely + * required) to supply a locator: if it does so, it must supply + * the locator to the application by invoking this method before + * invoking any of the other methods in the ContentHandler + * interface.</p> + * + * <p>The locator allows the application to determine the end + * position of any document-related event, even if the parser is + * not reporting an error. Typically, the application will + * use this information for reporting its own errors (such as + * character content that does not match an application's + * business rules). The information returned by the locator + * is probably not sufficient for use with a search engine.</p> + * + * <p>Note that the locator will return correct information only + * during the invocation SAX event callbacks after + * {@link #startDocument startDocument} returns and before + * {@link #endDocument endDocument} is called. The + * application should not attempt to use it at any other time.</p> + * + * @param locator an object that can return the location of + * any SAX document event + * @see org.xml.sax.Locator + */ + public void setDocumentLocator (Locator locator); + + + /** + * Receive notification of the beginning of a document. + * + * <p>The SAX parser will invoke this method only once, before any + * other event callbacks (except for {@link #setDocumentLocator + * setDocumentLocator}).</p> + * + * @throws org.xml.sax.SAXException any SAX exception, possibly + * wrapping another exception + * @see #endDocument + */ + public void startDocument () + throws SAXException; + + + /** + * Receive notification of the end of a document. + * + * <p><strong>There is an apparent contradiction between the + * documentation for this method and the documentation for {@link + * org.xml.sax.ErrorHandler#fatalError}. Until this ambiguity is + * resolved in a future major release, clients should make no + * assumptions about whether endDocument() will or will not be + * invoked when the parser has reported a fatalError() or thrown + * an exception.</strong></p> + * + * <p>The SAX parser will invoke this method only once, and it will + * be the last method invoked during the parse. The parser shall + * not invoke this method until it has either abandoned parsing + * (because of an unrecoverable error) or reached the end of + * input.</p> + * + * @throws org.xml.sax.SAXException any SAX exception, possibly + * wrapping another exception + * @see #startDocument + */ + public void endDocument() + throws SAXException; + + + /** + * Begin the scope of a prefix-URI Namespace mapping. + * + * <p>The information from this event is not necessary for + * normal Namespace processing: the SAX XML reader will + * automatically replace prefixes for element and attribute + * names when the <code>http://xml.org/sax/features/namespaces</code> + * feature is <var>true</var> (the default).</p> + * + * <p>There are cases, however, when applications need to + * use prefixes in character data or in attribute values, + * where they cannot safely be expanded automatically; the + * start/endPrefixMapping event supplies the information + * to the application to expand prefixes in those contexts + * itself, if necessary.</p> + * + * <p>Note that start/endPrefixMapping events are not + * guaranteed to be properly nested relative to each other: + * all startPrefixMapping events will occur immediately before the + * corresponding {@link #startElement startElement} event, + * and all {@link #endPrefixMapping endPrefixMapping} + * events will occur immediately after the corresponding + * {@link #endElement endElement} event, + * but their order is not otherwise + * guaranteed.</p> + * + * <p>There should never be start/endPrefixMapping events for the + * "xml" prefix, since it is predeclared and immutable.</p> + * + * @param prefix the Namespace prefix being declared. + * An empty string is used for the default element namespace, + * which has no prefix. + * @param uri the Namespace URI the prefix is mapped to + * @throws org.xml.sax.SAXException the client may throw + * an exception during processing + * @see #endPrefixMapping + * @see #startElement + */ + public void startPrefixMapping (String prefix, String uri) + throws SAXException; + + + /** + * End the scope of a prefix-URI mapping. + * + * <p>See {@link #startPrefixMapping startPrefixMapping} for + * details. These events will always occur immediately after the + * corresponding {@link #endElement endElement} event, but the order of + * {@link #endPrefixMapping endPrefixMapping} events is not otherwise + * guaranteed.</p> + * + * @param prefix the prefix that was being mapped. + * This is the empty string when a default mapping scope ends. + * @throws org.xml.sax.SAXException the client may throw + * an exception during processing + * @see #startPrefixMapping + * @see #endElement + */ + public void endPrefixMapping (String prefix) + throws SAXException; + + + /** + * Receive notification of the beginning of an element. + * + * <p>The Parser will invoke this method at the beginning of every + * element in the XML document; there will be a corresponding + * {@link #endElement endElement} event for every startElement event + * (even when the element is empty). All of the element's content will be + * reported, in order, before the corresponding endElement + * event.</p> + * + * <p>This event allows up to three name components for each + * element:</p> + * + * <ol> + * <li>the Namespace URI;</li> + * <li>the local name; and</li> + * <li>the qualified (prefixed) name.</li> + * </ol> + * + * <p>Any or all of these may be provided, depending on the + * values of the <var>http://xml.org/sax/features/namespaces</var> + * and the <var>http://xml.org/sax/features/namespace-prefixes</var> + * properties:</p> + * + * <ul> + * <li>the Namespace URI and local name are required when + * the namespaces property is <var>true</var> (the default), and are + * optional when the namespaces property is <var>false</var> (if one is + * specified, both must be);</li> + * <li>the qualified name is required when the namespace-prefixes property + * is <var>true</var>, and is optional when the namespace-prefixes property + * is <var>false</var> (the default).</li> + * </ul> + * + * <p>Note that the attribute list provided will contain only + * attributes with explicit values (specified or defaulted): + * #IMPLIED attributes will be omitted. The attribute list + * will contain attributes used for Namespace declarations + * (xmlns* attributes) only if the + * <code>http://xml.org/sax/features/namespace-prefixes</code> + * property is true (it is false by default, and support for a + * true value is optional).</p> + * + * <p>Like {@link #characters characters()}, attribute values may have + * characters that need more than one <code>char</code> value. </p> + * + * @param uri the Namespace URI, or the empty string if the + * element has no Namespace URI or if Namespace + * processing is not being performed + * @param localName the local name (without prefix), or the + * empty string if Namespace processing is not being + * performed + * @param qName the qualified name (with prefix), or the + * empty string if qualified names are not available + * @param atts the attributes attached to the element. If + * there are no attributes, it shall be an empty + * Attributes object. The value of this object after + * startElement returns is undefined + * @throws org.xml.sax.SAXException any SAX exception, possibly + * wrapping another exception + * @see #endElement + * @see org.xml.sax.Attributes + * @see org.xml.sax.helpers.AttributesImpl + */ + public void startElement (String uri, String localName, + String qName, Attributes atts) + throws SAXException; + + + /** + * Receive notification of the end of an element. + * + * <p>The SAX parser will invoke this method at the end of every + * element in the XML document; there will be a corresponding + * {@link #startElement startElement} event for every endElement + * event (even when the element is empty).</p> + * + * <p>For information on the names, see startElement.</p> + * + * @param uri the Namespace URI, or the empty string if the + * element has no Namespace URI or if Namespace + * processing is not being performed + * @param localName the local name (without prefix), or the + * empty string if Namespace processing is not being + * performed + * @param qName the qualified XML name (with prefix), or the + * empty string if qualified names are not available + * @throws org.xml.sax.SAXException any SAX exception, possibly + * wrapping another exception + */ + public void endElement (String uri, String localName, + String qName) + throws SAXException; + + + /** + * Receive notification of character data. + * + * <p>The Parser will call this method to report each chunk of + * character data. SAX parsers may return all contiguous character + * data in a single chunk, or they may split it into several + * chunks; however, all of the characters in any single event + * must come from the same external entity so that the Locator + * provides useful information.</p> + * + * <p>The application must not attempt to read from the array + * outside of the specified range.</p> + * + * <p>Individual characters may consist of more than one Java + * <code>char</code> value. There are two important cases where this + * happens, because characters can't be represented in just sixteen bits. + * In one case, characters are represented in a <em>Surrogate Pair</em>, + * using two special Unicode values. Such characters are in the so-called + * "Astral Planes", with a code point above U+FFFF. A second case involves + * composite characters, such as a base character combining with one or + * more accent characters. </p> + * + * <p> Your code should not assume that algorithms using + * <code>char</code>-at-a-time idioms will be working in character + * units; in some cases they will split characters. This is relevant + * wherever XML permits arbitrary characters, such as attribute values, + * processing instruction data, and comments as well as in data reported + * from this method. It's also generally relevant whenever Java code + * manipulates internationalized text; the issue isn't unique to XML.</p> + * + * <p>Note that some parsers will report whitespace in element + * content using the {@link #ignorableWhitespace ignorableWhitespace} + * method rather than this one (validating parsers <em>must</em> + * do so).</p> + * + * @param ch the characters from the XML document + * @param start the start position in the array + * @param length the number of characters to read from the array + * @throws org.xml.sax.SAXException any SAX exception, possibly + * wrapping another exception + * @see #ignorableWhitespace + * @see org.xml.sax.Locator + */ + public void characters (char ch[], int start, int length) + throws SAXException; + + + /** + * Receive notification of ignorable whitespace in element content. + * + * <p>Validating Parsers must use this method to report each chunk + * of whitespace in element content (see the W3C XML 1.0 + * recommendation, section 2.10): non-validating parsers may also + * use this method if they are capable of parsing and using + * content models.</p> + * + * <p>SAX parsers may return all contiguous whitespace in a single + * chunk, or they may split it into several chunks; however, all of + * the characters in any single event must come from the same + * external entity, so that the Locator provides useful + * information.</p> + * + * <p>The application must not attempt to read from the array + * outside of the specified range.</p> + * + * @param ch the characters from the XML document + * @param start the start position in the array + * @param length the number of characters to read from the array + * @throws org.xml.sax.SAXException any SAX exception, possibly + * wrapping another exception + * @see #characters + */ + public void ignorableWhitespace (char ch[], int start, int length) + throws SAXException; + + + /** + * Receive notification of a processing instruction. + * + * <p>The Parser will invoke this method once for each processing + * instruction found: note that processing instructions may occur + * before or after the main document element.</p> + * + * <p>A SAX parser must never report an XML declaration (XML 1.0, + * section 2.8) or a text declaration (XML 1.0, section 4.3.1) + * using this method.</p> + * + * <p>Like {@link #characters characters()}, processing instruction + * data may have characters that need more than one <code>char</code> + * value. </p> + * + * @param target the processing instruction target + * @param data the processing instruction data, or null if + * none was supplied. The data does not include any + * whitespace separating it from the target + * @throws org.xml.sax.SAXException any SAX exception, possibly + * wrapping another exception + */ + public void processingInstruction (String target, String data) + throws SAXException; + + + /** + * Receive notification of a skipped entity. + * This is not called for entity references within markup constructs + * such as element start tags or markup declarations. (The XML + * recommendation requires reporting skipped external entities. + * SAX also reports internal entity expansion/non-expansion, except + * within markup constructs.) + * + * <p>The Parser will invoke this method each time the entity is + * skipped. Non-validating processors may skip entities if they + * have not seen the declarations (because, for example, the + * entity was declared in an external DTD subset). All processors + * may skip external entities, depending on the values of the + * <code>http://xml.org/sax/features/external-general-entities</code> + * and the + * <code>http://xml.org/sax/features/external-parameter-entities</code> + * properties.</p> + * + * @param name the name of the skipped entity. If it is a + * parameter entity, the name will begin with '%', and if + * it is the external DTD subset, it will be the string + * "[dtd]" + * @throws org.xml.sax.SAXException any SAX exception, possibly + * wrapping another exception + */ + public void skippedEntity (String name) + throws SAXException; +} + +// end of ContentHandler.java diff --git a/xml/src/main/java/org/xml/sax/DTDHandler.java b/xml/src/main/java/org/xml/sax/DTDHandler.java new file mode 100644 index 0000000..13d5eee --- /dev/null +++ b/xml/src/main/java/org/xml/sax/DTDHandler.java @@ -0,0 +1,117 @@ +// SAX DTD handler. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: DTDHandler.java,v 1.8 2002/01/30 21:13:43 dbrownell Exp $ + +package org.xml.sax; + +/** + * Receive notification of basic DTD-related events. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>If a SAX application needs information about notations and + * unparsed entities, then the application implements this + * interface and registers an instance with the SAX parser using + * the parser's setDTDHandler method. The parser uses the + * instance to report notation and unparsed entity declarations to + * the application.</p> + * + * <p>Note that this interface includes only those DTD events that + * the XML recommendation <em>requires</em> processors to report: + * notation and unparsed entity declarations.</p> + * + * <p>The SAX parser may report these events in any order, regardless + * of the order in which the notations and unparsed entities were + * declared; however, all DTD events must be reported after the + * document handler's startDocument event, and before the first + * startElement event. + * (If the {@link org.xml.sax.ext.LexicalHandler LexicalHandler} is + * used, these events must also be reported before the endDTD event.) + * </p> + * + * <p>It is up to the application to store the information for + * future use (perhaps in a hash table or object tree). + * If the application encounters attributes of type "NOTATION", + * "ENTITY", or "ENTITIES", it can use the information that it + * obtained through this interface to find the entity and/or + * notation corresponding with the attribute value.</p> + * + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.XMLReader#setDTDHandler + */ +public interface DTDHandler { + + + /** + * Receive notification of a notation declaration event. + * + * <p>It is up to the application to record the notation for later + * reference, if necessary; + * notations may appear as attribute values and in unparsed entity + * declarations, and are sometime used with processing instruction + * target names.</p> + * + * <p>At least one of publicId and systemId must be non-null. + * If a system identifier is present, and it is a URL, the SAX + * parser must resolve it fully before passing it to the + * application through this event.</p> + * + * <p>There is no guarantee that the notation declaration will be + * reported before any unparsed entities that use it.</p> + * + * @param name The notation name. + * @param publicId The notation's public identifier, or null if + * none was given. + * @param systemId The notation's system identifier, or null if + * none was given. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #unparsedEntityDecl + * @see org.xml.sax.Attributes + */ + public abstract void notationDecl (String name, + String publicId, + String systemId) + throws SAXException; + + + /** + * Receive notification of an unparsed entity declaration event. + * + * <p>Note that the notation name corresponds to a notation + * reported by the {@link #notationDecl notationDecl} event. + * It is up to the application to record the entity for later + * reference, if necessary; + * unparsed entities may appear as attribute values. + * </p> + * + * <p>If the system identifier is a URL, the parser must resolve it + * fully before passing it to the application.</p> + * + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @param name The unparsed entity's name. + * @param publicId The entity's public identifier, or null if none + * was given. + * @param systemId The entity's system identifier. + * @param notationName The name of the associated notation. + * @see #notationDecl + * @see org.xml.sax.Attributes + */ + public abstract void unparsedEntityDecl (String name, + String publicId, + String systemId, + String notationName) + throws SAXException; + +} + +// end of DTDHandler.java diff --git a/xml/src/main/java/org/xml/sax/DocumentHandler.java b/xml/src/main/java/org/xml/sax/DocumentHandler.java new file mode 100644 index 0000000..500fe4c --- /dev/null +++ b/xml/src/main/java/org/xml/sax/DocumentHandler.java @@ -0,0 +1,232 @@ +// SAX document handler. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: DocumentHandler.java,v 1.6 2002/01/30 21:13:43 dbrownell Exp $ + +package org.xml.sax; + +/** + * Receive notification of general document events. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This was the main event-handling interface for SAX1; in + * SAX2, it has been replaced by {@link org.xml.sax.ContentHandler + * ContentHandler}, which provides Namespace support and reporting + * of skipped entities. This interface is included in SAX2 only + * to support legacy SAX1 applications.</p> + * + * <p>The order of events in this interface is very important, and + * mirrors the order of information in the document itself. For + * example, all of an element's content (character data, processing + * instructions, and/or subelements) will appear, in order, between + * the startElement event and the corresponding endElement event.</p> + * + * <p>Application writers who do not want to implement the entire + * interface can derive a class from HandlerBase, which implements + * the default functionality; parser writers can instantiate + * HandlerBase to obtain a default handler. The application can find + * the location of any document event using the Locator interface + * supplied by the Parser through the setDocumentLocator method.</p> + * + * @deprecated This interface has been replaced by the SAX2 + * {@link org.xml.sax.ContentHandler ContentHandler} + * interface, which includes Namespace support. + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.Parser#setDocumentHandler + * @see org.xml.sax.Locator + * @see org.xml.sax.HandlerBase + */ +public interface DocumentHandler { + + + /** + * Receive an object for locating the origin of SAX document events. + * + * <p>SAX parsers are strongly encouraged (though not absolutely + * required) to supply a locator: if it does so, it must supply + * the locator to the application by invoking this method before + * invoking any of the other methods in the DocumentHandler + * interface.</p> + * + * <p>The locator allows the application to determine the end + * position of any document-related event, even if the parser is + * not reporting an error. Typically, the application will + * use this information for reporting its own errors (such as + * character content that does not match an application's + * business rules). The information returned by the locator + * is probably not sufficient for use with a search engine.</p> + * + * <p>Note that the locator will return correct information only + * during the invocation of the events in this interface. The + * application should not attempt to use it at any other time.</p> + * + * @param locator An object that can return the location of + * any SAX document event. + * @see org.xml.sax.Locator + */ + public abstract void setDocumentLocator (Locator locator); + + + /** + * Receive notification of the beginning of a document. + * + * <p>The SAX parser will invoke this method only once, before any + * other methods in this interface or in DTDHandler (except for + * setDocumentLocator).</p> + * + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + */ + public abstract void startDocument () + throws SAXException; + + + /** + * Receive notification of the end of a document. + * + * <p>The SAX parser will invoke this method only once, and it will + * be the last method invoked during the parse. The parser shall + * not invoke this method until it has either abandoned parsing + * (because of an unrecoverable error) or reached the end of + * input.</p> + * + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + */ + public abstract void endDocument () + throws SAXException; + + + /** + * Receive notification of the beginning of an element. + * + * <p>The Parser will invoke this method at the beginning of every + * element in the XML document; there will be a corresponding + * endElement() event for every startElement() event (even when the + * element is empty). All of the element's content will be + * reported, in order, before the corresponding endElement() + * event.</p> + * + * <p>If the element name has a namespace prefix, the prefix will + * still be attached. Note that the attribute list provided will + * contain only attributes with explicit values (specified or + * defaulted): #IMPLIED attributes will be omitted.</p> + * + * @param name The element type name. + * @param atts The attributes attached to the element, if any. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #endElement + * @see org.xml.sax.AttributeList + */ + public abstract void startElement (String name, AttributeList atts) + throws SAXException; + + + /** + * Receive notification of the end of an element. + * + * <p>The SAX parser will invoke this method at the end of every + * element in the XML document; there will be a corresponding + * startElement() event for every endElement() event (even when the + * element is empty).</p> + * + * <p>If the element name has a namespace prefix, the prefix will + * still be attached to the name.</p> + * + * @param name The element type name + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + */ + public abstract void endElement (String name) + throws SAXException; + + + /** + * Receive notification of character data. + * + * <p>The Parser will call this method to report each chunk of + * character data. SAX parsers may return all contiguous character + * data in a single chunk, or they may split it into several + * chunks; however, all of the characters in any single event + * must come from the same external entity, so that the Locator + * provides useful information.</p> + * + * <p>The application must not attempt to read from the array + * outside of the specified range.</p> + * + * <p>Note that some parsers will report whitespace using the + * ignorableWhitespace() method rather than this one (validating + * parsers must do so).</p> + * + * @param ch The characters from the XML document. + * @param start The start position in the array. + * @param length The number of characters to read from the array. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #ignorableWhitespace + * @see org.xml.sax.Locator + */ + public abstract void characters (char ch[], int start, int length) + throws SAXException; + + + /** + * Receive notification of ignorable whitespace in element content. + * + * <p>Validating Parsers must use this method to report each chunk + * of ignorable whitespace (see the W3C XML 1.0 recommendation, + * section 2.10): non-validating parsers may also use this method + * if they are capable of parsing and using content models.</p> + * + * <p>SAX parsers may return all contiguous whitespace in a single + * chunk, or they may split it into several chunks; however, all of + * the characters in any single event must come from the same + * external entity, so that the Locator provides useful + * information.</p> + * + * <p>The application must not attempt to read from the array + * outside of the specified range.</p> + * + * @param ch The characters from the XML document. + * @param start The start position in the array. + * @param length The number of characters to read from the array. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see #characters + */ + public abstract void ignorableWhitespace (char ch[], int start, int length) + throws SAXException; + + + /** + * Receive notification of a processing instruction. + * + * <p>The Parser will invoke this method once for each processing + * instruction found: note that processing instructions may occur + * before or after the main document element.</p> + * + * <p>A SAX parser should never report an XML declaration (XML 1.0, + * section 2.8) or a text declaration (XML 1.0, section 4.3.1) + * using this method.</p> + * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if + * none was supplied. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + */ + public abstract void processingInstruction (String target, String data) + throws SAXException; + +} + +// end of DocumentHandler.java diff --git a/xml/src/main/java/org/xml/sax/EntityResolver.java b/xml/src/main/java/org/xml/sax/EntityResolver.java new file mode 100644 index 0000000..06ac725 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/EntityResolver.java @@ -0,0 +1,119 @@ +// SAX entity resolver. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: EntityResolver.java,v 1.10 2002/01/30 21:13:44 dbrownell Exp $ + +package org.xml.sax; + +import java.io.IOException; + + +/** + * Basic interface for resolving entities. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>If a SAX application needs to implement customized handling + * for external entities, it must implement this interface and + * register an instance with the SAX driver using the + * {@link org.xml.sax.XMLReader#setEntityResolver setEntityResolver} + * method.</p> + * + * <p>The XML reader will then allow the application to intercept any + * external entities (including the external DTD subset and external + * parameter entities, if any) before including them.</p> + * + * <p>Many SAX applications will not need to implement this interface, + * but it will be especially useful for applications that build + * XML documents from databases or other specialised input sources, + * or for applications that use URI types other than URLs.</p> + * + * <p>The following resolver would provide the application + * with a special character stream for the entity with the system + * identifier "http://www.myhost.com/today":</p> + * + * <pre> + * import org.xml.sax.EntityResolver; + * import org.xml.sax.InputSource; + * + * public class MyResolver implements EntityResolver { + * public InputSource resolveEntity (String publicId, String systemId) + * { + * if (systemId.equals("http://www.myhost.com/today")) { + * // return a special input source + * MyReader reader = new MyReader(); + * return new InputSource(reader); + * } else { + * // use the default behaviour + * return null; + * } + * } + * } + * </pre> + * + * <p>The application can also use this interface to redirect system + * identifiers to local URIs or to look up replacements in a catalog + * (possibly by using the public identifier).</p> + * + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.XMLReader#setEntityResolver + * @see org.xml.sax.InputSource + */ +public interface EntityResolver { + + + /** + * Allow the application to resolve external entities. + * + * <p>The parser will call this method before opening any external + * entity except the top-level document entity. Such entities include + * the external DTD subset and external parameter entities referenced + * within the DTD (in either case, only if the parser reads external + * parameter entities), and external general entities referenced + * within the document element (if the parser reads external general + * entities). The application may request that the parser locate + * the entity itself, that it use an alternative URI, or that it + * use data provided by the application (as a character or byte + * input stream).</p> + * + * <p>Application writers can use this method to redirect external + * system identifiers to secure and/or local URIs, to look up + * public identifiers in a catalogue, or to read an entity from a + * database or other input source (including, for example, a dialog + * box). Neither XML nor SAX specifies a preferred policy for using + * public or system IDs to resolve resources. However, SAX specifies + * how to interpret any InputSource returned by this method, and that + * if none is returned, then the system ID will be dereferenced as + * a URL. </p> + * + * <p>If the system identifier is a URL, the SAX parser must + * resolve it fully before reporting it to the application.</p> + * + * @param publicId The public identifier of the external entity + * being referenced, or null if none was supplied. + * @param systemId The system identifier of the external entity + * being referenced. + * @return An InputSource object describing the new input source, + * or null to request that the parser open a regular + * URI connection to the system identifier. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception java.io.IOException A Java-specific IO exception, + * possibly the result of creating a new InputStream + * or Reader for the InputSource. + * @see org.xml.sax.InputSource + */ + public abstract InputSource resolveEntity (String publicId, + String systemId) + throws SAXException, IOException; + +} + +// end of EntityResolver.java diff --git a/xml/src/main/java/org/xml/sax/ErrorHandler.java b/xml/src/main/java/org/xml/sax/ErrorHandler.java new file mode 100644 index 0000000..e4e4206 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ErrorHandler.java @@ -0,0 +1,139 @@ +// SAX error handler. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: ErrorHandler.java,v 1.10 2004/03/08 13:01:00 dmegginson Exp $ + +package org.xml.sax; + + +/** + * Basic interface for SAX error handlers. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>If a SAX application needs to implement customized error + * handling, it must implement this interface and then register an + * instance with the XML reader using the + * {@link org.xml.sax.XMLReader#setErrorHandler setErrorHandler} + * method. The parser will then report all errors and warnings + * through this interface.</p> + * + * <p><strong>WARNING:</strong> If an application does <em>not</em> + * register an ErrorHandler, XML parsing errors will go unreported, + * except that <em>SAXParseException</em>s will be thrown for fatal errors. + * In order to detect validity errors, an ErrorHandler that does something + * with {@link #error error()} calls must be registered.</p> + * + * <p>For XML processing errors, a SAX driver must use this interface + * in preference to throwing an exception: it is up to the application + * to decide whether to throw an exception for different types of + * errors and warnings. Note, however, that there is no requirement that + * the parser continue to report additional errors after a call to + * {@link #fatalError fatalError}. In other words, a SAX driver class + * may throw an exception after reporting any fatalError. + * Also parsers may throw appropriate exceptions for non-XML errors. + * For example, {@link XMLReader#parse XMLReader.parse()} would throw + * an IOException for errors accessing entities or the document.</p> + * + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1+ (sax2r3pre1) + * @see org.xml.sax.XMLReader#setErrorHandler + * @see org.xml.sax.SAXParseException + */ +public interface ErrorHandler { + + + /** + * Receive notification of a warning. + * + * <p>SAX parsers will use this method to report conditions that + * are not errors or fatal errors as defined by the XML + * recommendation. The default behaviour is to take no + * action.</p> + * + * <p>The SAX parser must continue to provide normal parsing events + * after invoking this method: it should still be possible for the + * application to process the document through to the end.</p> + * + * <p>Filters may use this method to report other, non-XML warnings + * as well.</p> + * + * @param exception The warning information encapsulated in a + * SAX parse exception. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.SAXParseException + */ + public abstract void warning (SAXParseException exception) + throws SAXException; + + + /** + * Receive notification of a recoverable error. + * + * <p>This corresponds to the definition of "error" in section 1.2 + * of the W3C XML 1.0 Recommendation. For example, a validating + * parser would use this callback to report the violation of a + * validity constraint. The default behaviour is to take no + * action.</p> + * + * <p>The SAX parser must continue to provide normal parsing + * events after invoking this method: it should still be possible + * for the application to process the document through to the end. + * If the application cannot do so, then the parser should report + * a fatal error even if the XML recommendation does not require + * it to do so.</p> + * + * <p>Filters may use this method to report other, non-XML errors + * as well.</p> + * + * @param exception The error information encapsulated in a + * SAX parse exception. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.SAXParseException + */ + public abstract void error (SAXParseException exception) + throws SAXException; + + + /** + * Receive notification of a non-recoverable error. + * + * <p><strong>There is an apparent contradiction between the + * documentation for this method and the documentation for {@link + * org.xml.sax.ContentHandler#endDocument}. Until this ambiguity + * is resolved in a future major release, clients should make no + * assumptions about whether endDocument() will or will not be + * invoked when the parser has reported a fatalError() or thrown + * an exception.</strong></p> + * + * <p>This corresponds to the definition of "fatal error" in + * section 1.2 of the W3C XML 1.0 Recommendation. For example, a + * parser would use this callback to report the violation of a + * well-formedness constraint.</p> + * + * <p>The application must assume that the document is unusable + * after the parser has invoked this method, and should continue + * (if at all) only for the sake of collecting additional error + * messages: in fact, SAX parsers are free to stop reporting any + * other events once this method has been invoked.</p> + * + * @param exception The error information encapsulated in a + * SAX parse exception. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.SAXParseException + */ + public abstract void fatalError (SAXParseException exception) + throws SAXException; + +} + +// end of ErrorHandler.java diff --git a/xml/src/main/java/org/xml/sax/HandlerBase.java b/xml/src/main/java/org/xml/sax/HandlerBase.java new file mode 100644 index 0000000..15ea2d4 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/HandlerBase.java @@ -0,0 +1,369 @@ +// SAX default handler base class. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: HandlerBase.java,v 1.7 2004/04/26 17:34:34 dmegginson Exp $ + +package org.xml.sax; + +/** + * Default base class for handlers. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class implements the default behaviour for four SAX1 + * interfaces: EntityResolver, DTDHandler, DocumentHandler, + * and ErrorHandler. It is now obsolete, but is included in SAX2 to + * support legacy SAX1 applications. SAX2 applications should use + * the {@link org.xml.sax.helpers.DefaultHandler DefaultHandler} + * class instead.</p> + * + * <p>Application writers can extend this class when they need to + * implement only part of an interface; parser writers can + * instantiate this class to provide default handlers when the + * application has not supplied its own.</p> + * + * <p>Note that the use of this class is optional.</p> + * + * @deprecated This class works with the deprecated + * {@link org.xml.sax.DocumentHandler DocumentHandler} + * interface. It has been replaced by the SAX2 + * {@link org.xml.sax.helpers.DefaultHandler DefaultHandler} + * class. + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.EntityResolver + * @see org.xml.sax.DTDHandler + * @see org.xml.sax.DocumentHandler + * @see org.xml.sax.ErrorHandler + */ +public class HandlerBase + implements EntityResolver, DTDHandler, DocumentHandler, ErrorHandler +{ + + + //////////////////////////////////////////////////////////////////// + // Default implementation of the EntityResolver interface. + //////////////////////////////////////////////////////////////////// + + /** + * Resolve an external entity. + * + * <p>Always return null, so that the parser will use the system + * identifier provided in the XML document. This method implements + * the SAX default behaviour: application writers can override it + * in a subclass to do special translations such as catalog lookups + * or URI redirection.</p> + * + * @param publicId The public identifer, 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 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 SAXException + { + return null; + } + + + + //////////////////////////////////////////////////////////////////// + // Default implementation of DTDHandler interface. + //////////////////////////////////////////////////////////////////// + + + /** + * Receive notification of a notation declaration. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass if they wish to keep track of the notations + * declared in a document.</p> + * + * @param name The notation name. + * @param publicId The notation public identifier, or null if not + * available. + * @param systemId The notation system identifier. + * @see org.xml.sax.DTDHandler#notationDecl + */ + public void notationDecl (String name, String publicId, String systemId) + { + // no op + } + + + /** + * Receive notification of an unparsed entity declaration. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to keep track of the unparsed entities + * declared in a document.</p> + * + * @param name The entity name. + * @param publicId The entity public identifier, or null if not + * available. + * @param systemId The entity system identifier. + * @param notationName The name of the associated notation. + * @see org.xml.sax.DTDHandler#unparsedEntityDecl + */ + public void unparsedEntityDecl (String name, String publicId, + String systemId, String notationName) + { + // no op + } + + + + //////////////////////////////////////////////////////////////////// + // Default implementation of DocumentHandler interface. + //////////////////////////////////////////////////////////////////// + + + /** + * Receive a Locator object for document events. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass if they wish to store the locator for use + * with other document events.</p> + * + * @param locator A locator for all SAX document events. + * @see org.xml.sax.DocumentHandler#setDocumentLocator + * @see org.xml.sax.Locator + */ + public void setDocumentLocator (Locator locator) + { + // no op + } + + + /** + * Receive notification of the beginning of the document. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the beginning + * of a document (such as allocating the root node of a tree or + * creating an output file).</p> + * + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DocumentHandler#startDocument + */ + public void startDocument () + throws SAXException + { + // no op + } + + + /** + * Receive notification of the end of the document. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the beginning + * of a document (such as finalising a tree or closing an output + * file).</p> + * + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DocumentHandler#endDocument + */ + public void endDocument () + throws SAXException + { + // no op + } + + + /** + * Receive notification of the start of an element. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the start of + * each element (such as allocating a new tree node or writing + * output to a file).</p> + * + * @param name The element type name. + * @param attributes The specified or defaulted attributes. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DocumentHandler#startElement + */ + public void startElement (String name, AttributeList attributes) + throws SAXException + { + // no op + } + + + /** + * Receive notification of the end of an element. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each element (such as finalising a tree node or writing + * output to a file).</p> + * + * @param name the element name + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DocumentHandler#endElement + */ + public void endElement (String name) + throws SAXException + { + // no op + } + + + /** + * Receive notification of character data inside an element. + * + * <p>By default, do nothing. Application writers may override this + * method to take specific actions for each chunk of character data + * (such as adding the data to a node or buffer, or printing it to + * a file).</p> + * + * @param ch The characters. + * @param start The start position in the character array. + * @param length The number of characters to use from the + * character array. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DocumentHandler#characters + */ + public void characters (char ch[], int start, int length) + throws SAXException + { + // no op + } + + + /** + * Receive notification of ignorable whitespace in element content. + * + * <p>By default, do nothing. Application writers may override this + * method to take specific actions for each chunk of ignorable + * whitespace (such as adding data to a node or buffer, or printing + * it to a file).</p> + * + * @param ch The whitespace characters. + * @param start The start position in the character array. + * @param length The number of characters to use from the + * character array. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DocumentHandler#ignorableWhitespace + */ + public void ignorableWhitespace (char ch[], int start, int length) + throws SAXException + { + // no op + } + + + /** + * Receive notification of a processing instruction. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions for each + * processing instruction, such as setting status variables or + * invoking other methods.</p> + * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if + * none is supplied. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DocumentHandler#processingInstruction + */ + public void processingInstruction (String target, String data) + throws SAXException + { + // no op + } + + + + //////////////////////////////////////////////////////////////////// + // Default implementation of the ErrorHandler interface. + //////////////////////////////////////////////////////////////////// + + + /** + * Receive notification of a parser warning. + * + * <p>The default implementation does nothing. Application writers + * may override this method in a subclass to take specific actions + * for each warning, such as inserting the message in a log file or + * printing it to the console.</p> + * + * @param e The warning information encoded as an exception. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ErrorHandler#warning + * @see org.xml.sax.SAXParseException + */ + public void warning (SAXParseException e) + throws SAXException + { + // no op + } + + + /** + * Receive notification of a recoverable parser error. + * + * <p>The default implementation does nothing. Application writers + * may override this method in a subclass to take specific actions + * for each error, such as inserting the message in a log file or + * printing it to the console.</p> + * + * @param e The 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 error (SAXParseException e) + throws SAXException + { + // no op + } + + + /** + * Report a fatal XML parsing error. + * + * <p>The default implementation throws a SAXParseException. + * Application writers may override this method in a subclass if + * they need to take specific actions for each fatal error (such as + * collecting all of the errors into a single report): in any case, + * the application must stop all regular processing when this + * method is invoked, since the document is no longer reliable, and + * the parser may no longer report parsing events.</p> + * + * @param e The error information encoded as an exception. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ErrorHandler#fatalError + * @see org.xml.sax.SAXParseException + */ + public void fatalError (SAXParseException e) + throws SAXException + { + throw e; + } + +} + +// end of HandlerBase.java diff --git a/xml/src/main/java/org/xml/sax/InputSource.java b/xml/src/main/java/org/xml/sax/InputSource.java new file mode 100644 index 0000000..b1342ee --- /dev/null +++ b/xml/src/main/java/org/xml/sax/InputSource.java @@ -0,0 +1,337 @@ +// SAX input source. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: InputSource.java,v 1.9 2002/01/30 21:13:45 dbrownell Exp $ + +package org.xml.sax; + +import java.io.Reader; +import java.io.InputStream; + +/** + * A single input source for an XML entity. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class allows a SAX application to encapsulate information + * about an input source in a single object, which may include + * a public identifier, a system identifier, a byte stream (possibly + * with a specified encoding), and/or a character stream.</p> + * + * <p>There are two places that the application can deliver an + * input source to the parser: as the argument to the Parser.parse + * method, or as the return value of the EntityResolver.resolveEntity + * method.</p> + * + * <p>The SAX parser will use the InputSource object to determine how + * to read XML input. If there is a character stream available, the + * parser will read that stream directly, disregarding any text + * encoding declaration found in that stream. + * If there is no character stream, but there is + * a byte stream, the parser will use that byte stream, using the + * encoding specified in the InputSource or else (if no encoding is + * specified) autodetecting the character encoding using an algorithm + * such as the one in the XML specification. If neither a character + * stream nor a + * byte stream is available, the parser will attempt to open a URI + * connection to the resource identified by the system + * identifier.</p> + * + * <p>An InputSource object belongs to the application: the SAX parser + * shall never modify it in any way (it may modify a copy if + * necessary). However, standard processing of both byte and + * character streams is to close them on as part of end-of-parse cleanup, + * so applications should not attempt to re-use such streams after they + * have been handed to a parser. </p> + * + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.XMLReader#parse(org.xml.sax.InputSource) + * @see org.xml.sax.EntityResolver#resolveEntity + * @see java.io.InputStream + * @see java.io.Reader + */ +public class InputSource { + + /** + * Zero-argument default constructor. + * + * @see #setPublicId + * @see #setSystemId + * @see #setByteStream + * @see #setCharacterStream + * @see #setEncoding + */ + public InputSource () + { + } + + + /** + * Create a new input source with a system identifier. + * + * <p>Applications may use setPublicId to include a + * public identifier as well, or setEncoding to specify + * the character encoding, if known.</p> + * + * <p>If the system identifier is a URL, it must be fully + * resolved (it may not be a relative URL).</p> + * + * @param systemId The system identifier (URI). + * @see #setPublicId + * @see #setSystemId + * @see #setByteStream + * @see #setEncoding + * @see #setCharacterStream + */ + public InputSource (String systemId) + { + setSystemId(systemId); + } + + + /** + * Create a new input source with a byte stream. + * + * <p>Application writers should use setSystemId() to provide a base + * for resolving relative URIs, may use setPublicId to include a + * public identifier, and may use setEncoding to specify the object's + * character encoding.</p> + * + * @param byteStream The raw byte stream containing the document. + * @see #setPublicId + * @see #setSystemId + * @see #setEncoding + * @see #setByteStream + * @see #setCharacterStream + */ + public InputSource (InputStream byteStream) + { + setByteStream(byteStream); + } + + + /** + * Create a new input source with a character stream. + * + * <p>Application writers should use setSystemId() to provide a base + * for resolving relative URIs, and may use setPublicId to include a + * public identifier.</p> + * + * <p>The character stream shall not include a byte order mark.</p> + * + * @param characterStream The raw character stream containing the document. + * @see #setPublicId + * @see #setSystemId + * @see #setByteStream + * @see #setCharacterStream + */ + public InputSource (Reader characterStream) + { + setCharacterStream(characterStream); + } + + + /** + * Set the public identifier for this input source. + * + * <p>The public identifier is always optional: if the application + * writer includes one, it will be provided as part of the + * location information.</p> + * + * @param publicId The public identifier as a string. + * @see #getPublicId + * @see org.xml.sax.Locator#getPublicId + * @see org.xml.sax.SAXParseException#getPublicId + */ + public void setPublicId (String publicId) + { + this.publicId = publicId; + } + + + /** + * Get the public identifier for this input source. + * + * @return The public identifier, or null if none was supplied. + * @see #setPublicId + */ + public String getPublicId () + { + return publicId; + } + + + /** + * Set the system identifier for this input source. + * + * <p>The system identifier is optional if there is a byte stream + * or a character stream, but it is still useful to provide one, + * since the application can use it to resolve relative URIs + * and can include it in error messages and warnings (the parser + * will attempt to open a connection to the URI only if + * there is no byte stream or character stream specified).</p> + * + * <p>If the application knows the character encoding of the + * object pointed to by the system identifier, it can register + * the encoding using the setEncoding method.</p> + * + * <p>If the system identifier is a URL, it must be fully + * resolved (it may not be a relative URL).</p> + * + * @param systemId The system identifier as a string. + * @see #setEncoding + * @see #getSystemId + * @see org.xml.sax.Locator#getSystemId + * @see org.xml.sax.SAXParseException#getSystemId + */ + public void setSystemId (String systemId) + { + this.systemId = systemId; + } + + + /** + * Get the system identifier for this input source. + * + * <p>The getEncoding method will return the character encoding + * of the object pointed to, or null if unknown.</p> + * + * <p>If the system ID is a URL, it will be fully resolved.</p> + * + * @return The system identifier, or null if none was supplied. + * @see #setSystemId + * @see #getEncoding + */ + public String getSystemId () + { + return systemId; + } + + + /** + * Set the byte stream for this input source. + * + * <p>The SAX parser will ignore this if there is also a character + * stream specified, but it will use a byte stream in preference + * to opening a URI connection itself.</p> + * + * <p>If the application knows the character encoding of the + * byte stream, it should set it with the setEncoding method.</p> + * + * @param byteStream A byte stream containing an XML document or + * other entity. + * @see #setEncoding + * @see #getByteStream + * @see #getEncoding + * @see java.io.InputStream + */ + public void setByteStream (InputStream byteStream) + { + this.byteStream = byteStream; + } + + + /** + * Get the byte stream for this input source. + * + * <p>The getEncoding method will return the character + * encoding for this byte stream, or null if unknown.</p> + * + * @return The byte stream, or null if none was supplied. + * @see #getEncoding + * @see #setByteStream + */ + public InputStream getByteStream () + { + return byteStream; + } + + + /** + * Set the character encoding, if known. + * + * <p>The encoding must be a string acceptable for an + * XML encoding declaration (see section 4.3.3 of the XML 1.0 + * recommendation).</p> + * + * <p>This method has no effect when the application provides a + * character stream.</p> + * + * @param encoding A string describing the character encoding. + * @see #setSystemId + * @see #setByteStream + * @see #getEncoding + */ + public void setEncoding (String encoding) + { + this.encoding = encoding; + } + + + /** + * Get the character encoding for a byte stream or URI. + * This value will be ignored when the application provides a + * character stream. + * + * @return The encoding, or null if none was supplied. + * @see #setByteStream + * @see #getSystemId + * @see #getByteStream + */ + public String getEncoding () + { + return encoding; + } + + + /** + * Set the character stream for this input source. + * + * <p>If there is a character stream specified, the SAX parser + * will ignore any byte stream and will not attempt to open + * a URI connection to the system identifier.</p> + * + * @param characterStream The character stream containing the + * XML document or other entity. + * @see #getCharacterStream + * @see java.io.Reader + */ + public void setCharacterStream (Reader characterStream) + { + this.characterStream = characterStream; + } + + + /** + * Get the character stream for this input source. + * + * @return The character stream, or null if none was supplied. + * @see #setCharacterStream + */ + public Reader getCharacterStream () + { + return characterStream; + } + + + + //////////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////////// + + private String publicId; + private String systemId; + private InputStream byteStream; + private String encoding; + private Reader characterStream; + +} + +// end of InputSource.java diff --git a/xml/src/main/java/org/xml/sax/Locator.java b/xml/src/main/java/org/xml/sax/Locator.java new file mode 100644 index 0000000..f8f3484 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/Locator.java @@ -0,0 +1,136 @@ +// SAX locator interface for document events. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: Locator.java,v 1.8 2002/01/30 21:13:47 dbrownell Exp $ + +package org.xml.sax; + + +/** + * Interface for associating a SAX event with a document location. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>If a SAX parser provides location information to the SAX + * application, it does so by implementing this interface and then + * passing an instance to the application using the content + * handler's {@link org.xml.sax.ContentHandler#setDocumentLocator + * setDocumentLocator} method. The application can use the + * object to obtain the location of any other SAX event + * in the XML source document.</p> + * + * <p>Note that the results returned by the object will be valid only + * during the scope of each callback method: the application + * will receive unpredictable results if it attempts to use the + * locator at any other time, or after parsing completes.</p> + * + * <p>SAX parsers are not required to supply a locator, but they are + * very strongly encouraged to do so. If the parser supplies a + * locator, it must do so before reporting any other document events. + * If no locator has been set by the time the application receives + * the {@link org.xml.sax.ContentHandler#startDocument startDocument} + * event, the application should assume that a locator is not + * available.</p> + * + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.ContentHandler#setDocumentLocator + */ +public interface Locator { + + + /** + * Return the public identifier for the current document event. + * + * <p>The return value is the public identifier of the document + * entity or of the external parsed entity in which the markup + * triggering the event appears.</p> + * + * @return A string containing the public identifier, or + * null if none is available. + * @see #getSystemId + */ + public abstract String getPublicId (); + + + /** + * Return the system identifier for the current document event. + * + * <p>The return value is the system identifier of the document + * entity or of the external parsed entity in which the markup + * triggering the event appears.</p> + * + * <p>If the system identifier is a URL, the parser must resolve it + * fully before passing it to the application. For example, a file + * name must always be provided as a <em>file:...</em> URL, and other + * kinds of relative URI are also resolved against their bases.</p> + * + * @return A string containing the system identifier, or null + * if none is available. + * @see #getPublicId + */ + public abstract String getSystemId (); + + + /** + * Return the line number where the current document event ends. + * Lines are delimited by line ends, which are defined in + * the XML specification. + * + * <p><strong>Warning:</strong> The return value from the method + * is intended only as an approximation for the sake of diagnostics; + * it is not intended to provide sufficient information + * to edit the character content of the original XML document. + * In some cases, these "line" numbers match what would be displayed + * as columns, and in others they may not match the source text + * due to internal entity expansion. </p> + * + * <p>The return value is an approximation of the line number + * in the document entity or external parsed entity where the + * markup triggering the event appears.</p> + * + * <p>If possible, the SAX driver should provide the line position + * of the first character after the text associated with the document + * event. The first line is line 1.</p> + * + * @return The line number, or -1 if none is available. + * @see #getColumnNumber + */ + public abstract int getLineNumber (); + + + /** + * Return the column number where the current document event ends. + * This is one-based number of Java <code>char</code> values since + * the last line end. + * + * <p><strong>Warning:</strong> The return value from the method + * is intended only as an approximation for the sake of diagnostics; + * it is not intended to provide sufficient information + * to edit the character content of the original XML document. + * For example, when lines contain combining character sequences, wide + * characters, surrogate pairs, or bi-directional text, the value may + * not correspond to the column in a text editor's display. </p> + * + * <p>The return value is an approximation of the column number + * in the document entity or external parsed entity where the + * markup triggering the event appears.</p> + * + * <p>If possible, the SAX driver should provide the line position + * of the first character after the text associated with the document + * event. The first column in each line is column 1.</p> + * + * @return The column number, or -1 if none is available. + * @see #getLineNumber + */ + public abstract int getColumnNumber (); + +} + +// end of Locator.java diff --git a/xml/src/main/java/org/xml/sax/Parser.java b/xml/src/main/java/org/xml/sax/Parser.java new file mode 100644 index 0000000..67a5512 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/Parser.java @@ -0,0 +1,209 @@ +// SAX parser interface. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: Parser.java,v 1.6 2002/01/30 21:13:47 dbrownell Exp $ + +package org.xml.sax; + +import java.io.IOException; +import java.util.Locale; + + +/** + * Basic interface for SAX (Simple API for XML) parsers. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This was the main event supplier interface for SAX1; it has + * been replaced in SAX2 by {@link org.xml.sax.XMLReader XMLReader}, + * which includes Namespace support and sophisticated configurability + * and extensibility.</p> + * + * <p>All SAX1 parsers must implement this basic interface: it allows + * applications to register handlers for different types of events + * and to initiate a parse from a URI, or a character stream.</p> + * + * <p>All SAX1 parsers must also implement a zero-argument constructor + * (though other constructors are also allowed).</p> + * + * <p>SAX1 parsers are reusable but not re-entrant: the application + * may reuse a parser object (possibly with a different input source) + * once the first parse has completed successfully, but it may not + * invoke the parse() methods recursively within a parse.</p> + * + * @deprecated This interface has been replaced by the SAX2 + * {@link org.xml.sax.XMLReader XMLReader} + * interface, which includes Namespace support. + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.EntityResolver + * @see org.xml.sax.DTDHandler + * @see org.xml.sax.DocumentHandler + * @see org.xml.sax.ErrorHandler + * @see org.xml.sax.HandlerBase + * @see org.xml.sax.InputSource + */ +public interface Parser +{ + + /** + * Allow an application to request a locale for errors and warnings. + * + * <p>SAX parsers are not required to provide localisation for errors + * and warnings; if they cannot support the requested locale, + * however, they must throw a SAX exception. Applications may + * not request a locale change in the middle of a parse.</p> + * + * @param locale A Java Locale object. + * @exception org.xml.sax.SAXException Throws an exception + * (using the previous or default locale) if the + * requested locale is not supported. + * @see org.xml.sax.SAXException + * @see org.xml.sax.SAXParseException + */ + public abstract void setLocale (Locale locale) + throws SAXException; + + + /** + * Allow an application to register a custom entity resolver. + * + * <p>If the application does not register an entity resolver, the + * SAX parser will resolve system identifiers and open connections + * to entities itself (this is the default behaviour implemented in + * HandlerBase).</p> + * + * <p>Applications may register a new or different entity resolver + * in the middle of a parse, and the SAX parser must begin using + * the new resolver immediately.</p> + * + * @param resolver The object for resolving entities. + * @see EntityResolver + * @see HandlerBase + */ + public abstract void setEntityResolver (EntityResolver resolver); + + + /** + * Allow an application to register a DTD event handler. + * + * <p>If the application does not register a DTD handler, all DTD + * events reported by the SAX parser will be silently + * ignored (this is the default behaviour implemented by + * HandlerBase).</p> + * + * <p>Applications may register a new or different + * handler in the middle of a parse, and the SAX parser must + * begin using the new handler immediately.</p> + * + * @param handler The DTD handler. + * @see DTDHandler + * @see HandlerBase + */ + public abstract void setDTDHandler (DTDHandler handler); + + + /** + * Allow an application to register a document event handler. + * + * <p>If the application does not register a document handler, all + * document events reported by the SAX parser will be silently + * ignored (this is the default behaviour implemented by + * HandlerBase).</p> + * + * <p>Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.</p> + * + * @param handler The document handler. + * @see DocumentHandler + * @see HandlerBase + */ + public abstract void setDocumentHandler (DocumentHandler handler); + + + /** + * Allow an application to register an error event handler. + * + * <p>If the application does not register an error event handler, + * all error events reported by the SAX parser will be silently + * ignored, except for fatalError, which will throw a SAXException + * (this is the default behaviour implemented by HandlerBase).</p> + * + * <p>Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.</p> + * + * @param handler The error handler. + * @see ErrorHandler + * @see SAXException + * @see HandlerBase + */ + public abstract void setErrorHandler (ErrorHandler handler); + + + /** + * Parse an XML document. + * + * <p>The application can use this method to instruct the SAX parser + * to begin parsing an XML document from any valid input + * source (a character stream, a byte stream, or a URI).</p> + * + * <p>Applications may not invoke this method while a parse is in + * progress (they should create a new Parser instead for each + * additional XML document). Once a parse is complete, an + * application may reuse the same Parser object, possibly with a + * different input source.</p> + * + * @param source 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 #setDocumentHandler + * @see #setErrorHandler + */ + public abstract void parse (InputSource source) + throws SAXException, IOException; + + + /** + * Parse an XML document from a system identifier (URI). + * + * <p>This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact + * equivalent of the following:</p> + * + * <pre> + * parse(new InputSource(systemId)); + * </pre> + * + * <p>If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser.</p> + * + * @param systemId The system identifier (URI). + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception java.io.IOException An IO exception from the parser, + * possibly from a byte stream or character stream + * supplied by the application. + * @see #parse(org.xml.sax.InputSource) + */ + public abstract void parse (String systemId) + throws SAXException, IOException; + +} + +// end of Parser.java diff --git a/xml/src/main/java/org/xml/sax/SAXException.java b/xml/src/main/java/org/xml/sax/SAXException.java new file mode 100644 index 0000000..2e5b4cd --- /dev/null +++ b/xml/src/main/java/org/xml/sax/SAXException.java @@ -0,0 +1,153 @@ +// SAX exception class. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: SAXException.java,v 1.7 2002/01/30 21:13:48 dbrownell Exp $ + +package org.xml.sax; + +/** + * Encapsulate a general SAX error or warning. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class can contain basic error or warning information from + * either the XML parser or the application: a parser writer or + * application writer can subclass it to provide additional + * functionality. SAX handlers may throw this exception or + * any exception subclassed from it.</p> + * + * <p>If the application needs to pass through other types of + * exceptions, it must wrap those exceptions in a SAXException + * or an exception derived from a SAXException.</p> + * + * <p>If the parser or application needs to include information about a + * specific location in an XML document, it should use the + * {@link org.xml.sax.SAXParseException SAXParseException} subclass.</p> + * + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.SAXParseException + */ +public class SAXException extends Exception { + + + /** + * Create a new SAXException. + */ + public SAXException () + { + super(); + this.exception = null; + } + + + /** + * Create a new SAXException. + * + * @param message The error or warning message. + */ + public SAXException (String message) { + super(message); + this.exception = null; + } + + + /** + * Create a new SAXException wrapping an existing exception. + * + * <p>The existing exception will be embedded in the new + * one, and its message will become the default message for + * the SAXException.</p> + * + * @param e The exception to be wrapped in a SAXException. + */ + public SAXException (Exception e) + { + super(); + this.exception = e; + } + + + /** + * Create a new SAXException from an existing exception. + * + * <p>The existing exception will be embedded in the new + * one, but the new exception will have its own message.</p> + * + * @param message The detail message. + * @param e The exception to be wrapped in a SAXException. + */ + public SAXException (String message, Exception e) + { + super(message); + this.exception = e; + } + + + /** + * Return a detail message for this exception. + * + * <p>If there is an embedded exception, and if the SAXException + * has no detail message of its own, this method will return + * the detail message from the embedded exception.</p> + * + * @return The error or warning message. + */ + public String getMessage () + { + String message = super.getMessage(); + + if (message == null && exception != null) { + return exception.getMessage(); + } else { + return message; + } + } + + + /** + * Return the embedded exception, if any. + * + * @return The embedded exception, or null if there is none. + */ + public Exception getException () + { + return exception; + } + + + /** + * Override toString to pick up any embedded exception. + * + * @return A string representation of this exception. + */ + public String toString () + { + if (exception != null) { + return exception.toString(); + } else { + return super.toString(); + } + } + + + + ////////////////////////////////////////////////////////////////////// + // Internal state. + ////////////////////////////////////////////////////////////////////// + + + /** + * @serial The embedded exception if tunnelling, or null. + */ + private Exception exception; + +} + +// end of SAXException.java diff --git a/xml/src/main/java/org/xml/sax/SAXNotRecognizedException.java b/xml/src/main/java/org/xml/sax/SAXNotRecognizedException.java new file mode 100644 index 0000000..69ba807 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/SAXNotRecognizedException.java @@ -0,0 +1,53 @@ +// 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.7 2002/01/30 21:13:48 dbrownell Exp $ + +package org.xml.sax; + + +/** + * Exception class for an unrecognized identifier. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>An XMLReader will throw this exception when it finds an + * unrecognized feature or property identifier; SAX applications and + * extensions may use this class for other, similar purposes.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @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); + } + +} + +// end of SAXNotRecognizedException.java diff --git a/xml/src/main/java/org/xml/sax/SAXNotSupportedException.java b/xml/src/main/java/org/xml/sax/SAXNotSupportedException.java new file mode 100644 index 0000000..bd5b239 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/SAXNotSupportedException.java @@ -0,0 +1,53 @@ +// 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.7 2002/01/30 21:13:48 dbrownell Exp $ + +package org.xml.sax; + +/** + * Exception class for an unsupported operation. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>An XMLReader will throw this exception when it recognizes a + * feature or property identifier, but cannot perform the requested + * operation (setting a state or value). Other SAX2 applications and + * extensions may use this class for similar purposes.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @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); + } + +} + +// end of SAXNotSupportedException.java diff --git a/xml/src/main/java/org/xml/sax/SAXParseException.java b/xml/src/main/java/org/xml/sax/SAXParseException.java new file mode 100644 index 0000000..a6a93e9 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/SAXParseException.java @@ -0,0 +1,269 @@ +// SAX exception class. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: SAXParseException.java,v 1.11 2004/04/21 13:05:02 dmegginson Exp $ + +package org.xml.sax; + +/** + * Encapsulate an XML parse error or warning. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This exception may include information for locating the error + * in the original XML document, as if it came from a {@link Locator} + * object. Note that although the application + * will receive a SAXParseException as the argument to the handlers + * in the {@link org.xml.sax.ErrorHandler ErrorHandler} interface, + * the application is not actually required to throw the exception; + * instead, it can simply read the information in it and take a + * different action.</p> + * + * <p>Since this exception is a subclass of {@link org.xml.sax.SAXException + * SAXException}, it inherits the ability to wrap another exception.</p> + * + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.SAXException + * @see org.xml.sax.Locator + * @see org.xml.sax.ErrorHandler + */ +public class SAXParseException extends SAXException { + + + ////////////////////////////////////////////////////////////////////// + // Constructors. + ////////////////////////////////////////////////////////////////////// + + + /** + * Create a new SAXParseException from a message and a Locator. + * + * <p>This constructor is especially useful when an application is + * creating its own exception from within a {@link org.xml.sax.ContentHandler + * ContentHandler} callback.</p> + * + * @param message The error or warning message. + * @param locator The locator object for the error or warning (may be + * null). + * @see org.xml.sax.Locator + */ + public SAXParseException (String message, Locator locator) { + super(message); + if (locator != null) { + init(locator.getPublicId(), locator.getSystemId(), + locator.getLineNumber(), locator.getColumnNumber()); + } else { + init(null, null, -1, -1); + } + } + + + /** + * Wrap an existing exception in a SAXParseException. + * + * <p>This constructor is especially useful when an application is + * creating its own exception from within a {@link org.xml.sax.ContentHandler + * ContentHandler} callback, and needs to wrap an existing exception that is not a + * subclass of {@link org.xml.sax.SAXException SAXException}.</p> + * + * @param message The error or warning message, or null to + * use the message from the embedded exception. + * @param locator The locator object for the error or warning (may be + * null). + * @param e Any exception. + * @see org.xml.sax.Locator + */ + public SAXParseException (String message, Locator locator, + Exception e) { + super(message, e); + if (locator != null) { + init(locator.getPublicId(), locator.getSystemId(), + locator.getLineNumber(), locator.getColumnNumber()); + } else { + init(null, null, -1, -1); + } + } + + + /** + * Create a new SAXParseException. + * + * <p>This constructor is most useful for parser writers.</p> + * + * <p>All parameters except the message are as if + * they were provided by a {@link Locator}. For example, if the + * system identifier is a URL (including relative filename), the + * caller must resolve it fully before creating the exception.</p> + * + * + * @param message The error or warning message. + * @param publicId The public identifier of the entity that generated + * the error or warning. + * @param systemId The system identifier of the entity that generated + * the error or warning. + * @param lineNumber The line number of the end of the text that + * caused the error or warning. + * @param columnNumber The column number of the end of the text that + * cause the error or warning. + */ + public SAXParseException (String message, String publicId, String systemId, + int lineNumber, int columnNumber) + { + super(message); + init(publicId, systemId, lineNumber, columnNumber); + } + + + /** + * Create a new SAXParseException with an embedded exception. + * + * <p>This constructor is most useful for parser writers who + * need to wrap an exception that is not a subclass of + * {@link org.xml.sax.SAXException SAXException}.</p> + * + * <p>All parameters except the message and exception are as if + * they were provided by a {@link Locator}. For example, if the + * system identifier is a URL (including relative filename), the + * caller must resolve it fully before creating the exception.</p> + * + * @param message The error or warning message, or null to use + * the message from the embedded exception. + * @param publicId The public identifier of the entity that generated + * the error or warning. + * @param systemId The system identifier of the entity that generated + * the error or warning. + * @param lineNumber The line number of the end of the text that + * caused the error or warning. + * @param columnNumber The column number of the end of the text that + * cause the error or warning. + * @param e Another exception to embed in this one. + */ + public SAXParseException (String message, String publicId, String systemId, + int lineNumber, int columnNumber, Exception e) + { + super(message, e); + init(publicId, systemId, lineNumber, columnNumber); + } + + + /** + * Internal initialization method. + * + * @param publicId The public identifier of the entity which generated the exception, + * or null. + * @param systemId The system identifier of the entity which generated the exception, + * or null. + * @param lineNumber The line number of the error, or -1. + * @param columnNumber The column number of the error, or -1. + */ + private void init (String publicId, String systemId, + int lineNumber, int columnNumber) + { + this.publicId = publicId; + this.systemId = systemId; + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + } + + + /** + * Get the public identifier of the entity where the exception occurred. + * + * @return A string containing the public identifier, or null + * if none is available. + * @see org.xml.sax.Locator#getPublicId + */ + public String getPublicId () + { + return this.publicId; + } + + + /** + * Get the system identifier of the entity where the exception occurred. + * + * <p>If the system identifier is a URL, it will have been resolved + * fully.</p> + * + * @return A string containing the system identifier, or null + * if none is available. + * @see org.xml.sax.Locator#getSystemId + */ + public String getSystemId () + { + return this.systemId; + } + + + /** + * The line number of the end of the text where the exception occurred. + * + * <p>The first line is line 1.</p> + * + * @return An integer representing the line number, or -1 + * if none is available. + * @see org.xml.sax.Locator#getLineNumber + */ + public int getLineNumber () + { + return this.lineNumber; + } + + + /** + * The column number of the end of the text where the exception occurred. + * + * <p>The first column in a line is position 1.</p> + * + * @return An integer representing the column number, or -1 + * if none is available. + * @see org.xml.sax.Locator#getColumnNumber + */ + public int getColumnNumber () + { + return this.columnNumber; + } + + + ////////////////////////////////////////////////////////////////////// + // 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; + +} + +// end of SAXParseException.java diff --git a/xml/src/main/java/org/xml/sax/XMLFilter.java b/xml/src/main/java/org/xml/sax/XMLFilter.java new file mode 100644 index 0000000..5a399fa --- /dev/null +++ b/xml/src/main/java/org/xml/sax/XMLFilter.java @@ -0,0 +1,65 @@ +// XMLFilter.java - filter SAX2 events. +// http://www.saxproject.org +// Written by David Megginson +// NO WARRANTY! This class is in the Public Domain. +// $Id: XMLFilter.java,v 1.6 2002/01/30 21:13:48 dbrownell Exp $ + +package org.xml.sax; + + +/** + * Interface for an XML filter. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>An XML filter is like an XML reader, except that it obtains its + * events from another XML reader rather than a primary source like + * an XML document or database. Filters can modify a stream of + * events as they pass on to the final application.</p> + * + * <p>The XMLFilterImpl helper class provides a convenient base + * for creating SAX2 filters, by passing on all {@link org.xml.sax.EntityResolver + * EntityResolver}, {@link org.xml.sax.DTDHandler DTDHandler}, + * {@link org.xml.sax.ContentHandler ContentHandler} and {@link org.xml.sax.ErrorHandler + * ErrorHandler} events automatically.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.helpers.XMLFilterImpl + */ +public interface XMLFilter extends XMLReader +{ + + /** + * Set the parent reader. + * + * <p>This method allows the application to link the filter to + * a parent reader (which may be another filter). The argument + * may not be null.</p> + * + * @param parent The parent reader. + */ + public abstract void setParent (XMLReader parent); + + + /** + * Get the parent reader. + * + * <p>This method allows the application to query the parent + * reader (which may be another filter). It is generally a + * bad idea to perform any operations on the parent reader + * directly: they should all pass through this filter.</p> + * + * @return The parent filter, or null if none has been set. + */ + public abstract XMLReader getParent (); + +} + +// end of XMLFilter.java diff --git a/xml/src/main/java/org/xml/sax/XMLReader.java b/xml/src/main/java/org/xml/sax/XMLReader.java new file mode 100644 index 0000000..d58a4bd --- /dev/null +++ b/xml/src/main/java/org/xml/sax/XMLReader.java @@ -0,0 +1,404 @@ +// 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.9 2004/04/26 17:34:34 dmegginson Exp $ + +package org.xml.sax; + +import java.io.IOException; + + +/** + * Interface for reading an XML document using callbacks. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p><strong>Note:</strong> despite its name, this interface does + * <em>not</em> extend the standard Java {@link java.io.Reader Reader} + * interface, because reading XML is a fundamentally different activity + * than reading character data.</p> + * + * <p>XMLReader is the interface that an XML parser's SAX2 driver must + * implement. This interface allows an application to set and + * query features and properties in the parser, to register + * event handlers for document processing, and to initiate + * a document parse.</p> + * + * <p>All SAX interfaces are assumed to be synchronous: the + * {@link #parse parse} methods must not return until parsing + * is complete, and readers must wait for an event-handler callback + * to return before reporting the next event.</p> + * + * <p>This interface replaces the (now deprecated) SAX 1.0 {@link + * org.xml.sax.Parser Parser} interface. The XMLReader interface + * contains two important enhancements over the old Parser + * interface (as well as some minor ones):</p> + * + * <ol> + * <li>it adds a standard way to query and set features and + * properties; and</li> + * <li>it adds Namespace support, which is required for many + * higher-level XML standards.</li> + * </ol> + * + * <p>There are adapters available to convert a SAX1 Parser to + * a SAX2 XMLReader and vice-versa.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1+ (sax2r3pre1) + * @see org.xml.sax.XMLFilter + * @see org.xml.sax.helpers.ParserAdapter + * @see org.xml.sax.helpers.XMLReaderAdapter + */ +public interface XMLReader +{ + + + //////////////////////////////////////////////////////////////////// + // Configuration. + //////////////////////////////////////////////////////////////////// + + + /** + * Look up the value of a feature flag. + * + * <p>The feature name is any fully-qualified URI. It is + * possible for an XMLReader to recognize a feature name but + * temporarily be unable to return its value. + * Some feature values may be available only in specific + * contexts, such as before, during, or after a parse. + * Also, some feature values may not be programmatically accessible. + * (In the case of an adapter for SAX1 {@link Parser}, there is no + * implementation-independent way to expose whether the underlying + * parser is performing validation, expanding external entities, + * and so forth.) </p> + * + * <p>All XMLReaders are required to recognize the + * http://xml.org/sax/features/namespaces and the + * http://xml.org/sax/features/namespace-prefixes feature names.</p> + * + * <p>Typical usage is something like this:</p> + * + * <pre> + * XMLReader r = new MySAXDriver(); + * + * // try to activate validation + * try { + * r.setFeature("http://xml.org/sax/features/validation", true); + * } catch (SAXException e) { + * System.err.println("Cannot activate validation."); + * } + * + * // register event handlers + * r.setContentHandler(new MyContentHandler()); + * r.setErrorHandler(new MyErrorHandler()); + * + * // parse the first document + * try { + * r.parse("http://www.foo.com/mydoc.xml"); + * } catch (IOException e) { + * System.err.println("I/O exception reading XML document"); + * } catch (SAXException e) { + * System.err.println("XML exception reading document."); + * } + * </pre> + * + * <p>Implementors are free (and encouraged) to invent their own features, + * using names built on their own URIs.</p> + * + * @param name The feature name, which is a fully-qualified URI. + * @return The current value of the feature (true or false). + * @exception org.xml.sax.SAXNotRecognizedException If the feature + * value can't be assigned or retrieved. + * @exception org.xml.sax.SAXNotSupportedException When the + * XMLReader recognizes the feature name but + * cannot determine its value at this time. + * @see #setFeature + */ + public boolean getFeature (String name) + throws SAXNotRecognizedException, SAXNotSupportedException; + + + /** + * Set the value of a feature flag. + * + * <p>The feature name is any fully-qualified URI. It is + * possible for an XMLReader to expose a feature value but + * to be unable to change the current value. + * Some feature values may be immutable or mutable only + * in specific contexts, such as before, during, or after + * a parse.</p> + * + * <p>All XMLReaders are required to support setting + * http://xml.org/sax/features/namespaces to true and + * http://xml.org/sax/features/namespace-prefixes to false.</p> + * + * @param name The feature name, which is a fully-qualified URI. + * @param value The requested value of the feature (true or false). + * @exception org.xml.sax.SAXNotRecognizedException If the feature + * value can't be assigned or retrieved. + * @exception org.xml.sax.SAXNotSupportedException When the + * XMLReader recognizes the feature name but + * cannot set the requested value. + * @see #getFeature + */ + public void setFeature (String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException; + + + /** + * Look up the value of a property. + * + * <p>The property name is any fully-qualified URI. It is + * possible for an XMLReader to recognize a property name but + * temporarily be unable to return its value. + * Some property values may be available only in specific + * contexts, such as before, during, or after a parse.</p> + * + * <p>XMLReaders are not required to recognize any specific + * property names, though an initial core set is documented for + * SAX2.</p> + * + * <p>Implementors are free (and encouraged) to invent their own properties, + * using names built on their own URIs.</p> + * + * @param name The property name, which is a fully-qualified URI. + * @return The current value of the property. + * @exception org.xml.sax.SAXNotRecognizedException If the property + * value can't be assigned or retrieved. + * @exception org.xml.sax.SAXNotSupportedException When the + * XMLReader recognizes the property name but + * cannot determine its value at this time. + * @see #setProperty + */ + public Object getProperty (String name) + throws SAXNotRecognizedException, SAXNotSupportedException; + + + /** + * Set the value of a property. + * + * <p>The property name is any fully-qualified URI. It is + * possible for an XMLReader to recognize a property name but + * to be unable to change the current value. + * Some property values may be immutable or mutable only + * in specific contexts, such as before, during, or after + * a parse.</p> + * + * <p>XMLReaders are not required to recognize setting + * any specific property names, though a core set is defined by + * SAX2.</p> + * + * <p>This method is also the standard mechanism for setting + * extended handlers.</p> + * + * @param name The property name, which is a fully-qualified URI. + * @param value The requested value for the property. + * @exception org.xml.sax.SAXNotRecognizedException If the property + * value can't be assigned or retrieved. + * @exception org.xml.sax.SAXNotSupportedException When the + * XMLReader recognizes the property name but + * cannot set the requested value. + */ + public void setProperty (String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException; + + + + //////////////////////////////////////////////////////////////////// + // Event handlers. + //////////////////////////////////////////////////////////////////// + + + /** + * Allow an application to register an entity resolver. + * + * <p>If the application does not register an entity resolver, + * the XMLReader will perform its own default resolution.</p> + * + * <p>Applications may register a new or different resolver in the + * middle of a parse, and the SAX parser must begin using the new + * resolver immediately.</p> + * + * @param resolver The entity resolver. + * @see #getEntityResolver + */ + public void setEntityResolver (EntityResolver resolver); + + + /** + * Return the current entity resolver. + * + * @return The current entity resolver, or null if none + * has been registered. + * @see #setEntityResolver + */ + public EntityResolver getEntityResolver (); + + + /** + * Allow an application to register a DTD event handler. + * + * <p>If the application does not register a DTD handler, all DTD + * events reported by the SAX parser will be silently ignored.</p> + * + * <p>Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.</p> + * + * @param handler The DTD handler. + * @see #getDTDHandler + */ + public void setDTDHandler (DTDHandler handler); + + + /** + * Return the current DTD handler. + * + * @return The current DTD handler, or null if none + * has been registered. + * @see #setDTDHandler + */ + public DTDHandler getDTDHandler (); + + + /** + * Allow an application to register a content event handler. + * + * <p>If the application does not register a content handler, all + * content events reported by the SAX parser will be silently + * ignored.</p> + * + * <p>Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.</p> + * + * @param handler The content handler. + * @see #getContentHandler + */ + public void setContentHandler (ContentHandler handler); + + + /** + * Return the current content handler. + * + * @return The current content handler, or null if none + * has been registered. + * @see #setContentHandler + */ + public ContentHandler getContentHandler (); + + + /** + * Allow an application to register an error event handler. + * + * <p>If the application does not register an error handler, all + * error events reported by the SAX parser will be silently + * ignored; however, normal processing may not continue. It is + * highly recommended that all SAX applications implement an + * error handler to avoid unexpected bugs.</p> + * + * <p>Applications may register a new or different handler in the + * middle of a parse, and the SAX parser must begin using the new + * handler immediately.</p> + * + * @param handler The error handler. + * @see #getErrorHandler + */ + public void setErrorHandler (ErrorHandler handler); + + + /** + * Return the current error handler. + * + * @return The current error handler, or null if none + * has been registered. + * @see #setErrorHandler + */ + public ErrorHandler getErrorHandler (); + + + + //////////////////////////////////////////////////////////////////// + // Parsing. + //////////////////////////////////////////////////////////////////// + + /** + * Parse an XML document. + * + * <p>The application can use this method to instruct the XML + * reader to begin parsing an XML document from any valid input + * source (a character stream, a byte stream, or a URI).</p> + * + * <p>Applications may not invoke this method while a parse is in + * progress (they should create a new XMLReader instead for each + * nested XML document). Once a parse is complete, an + * application may reuse the same XMLReader object, possibly with a + * different input source. + * Configuration of the XMLReader object (such as handler bindings and + * values established for feature flags and properties) is unchanged + * by completion of a parse, unless the definition of that aspect of + * the configuration explicitly specifies other behavior. + * (For example, feature flags or properties exposing + * characteristics of the document being parsed.) + * </p> + * + * <p>During the parse, the XMLReader will provide information + * about the XML document through the registered event + * handlers.</p> + * + * <p>This method is synchronous: it will not return until parsing + * has ended. If a client application wants to terminate + * parsing early, it should throw an exception.</p> + * + * @param input The input source for the top-level of the + * XML document. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception java.io.IOException An IO exception from the parser, + * possibly from a byte stream or character stream + * supplied by the application. + * @see org.xml.sax.InputSource + * @see #parse(java.lang.String) + * @see #setEntityResolver + * @see #setDTDHandler + * @see #setContentHandler + * @see #setErrorHandler + */ + public void parse (InputSource input) + throws IOException, SAXException; + + + /** + * Parse an XML document from a system identifier (URI). + * + * <p>This method is a shortcut for the common case of reading a + * document from a system identifier. It is the exact + * equivalent of the following:</p> + * + * <pre> + * parse(new InputSource(systemId)); + * </pre> + * + * <p>If the system identifier is a URL, it must be fully resolved + * by the application before it is passed to the parser.</p> + * + * @param systemId The system identifier (URI). + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @exception java.io.IOException An IO exception from the parser, + * possibly from a byte stream or character stream + * supplied by the application. + * @see #parse(org.xml.sax.InputSource) + */ + public void parse (String systemId) + throws IOException, SAXException; + +} diff --git a/xml/src/main/java/org/xml/sax/ext/Attributes2.java b/xml/src/main/java/org/xml/sax/ext/Attributes2.java new file mode 100644 index 0000000..45cd551 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/Attributes2.java @@ -0,0 +1,132 @@ +// Attributes2.java - extended Attributes +// http://www.saxproject.org +// Public Domain: no warranty. +// $Id: Attributes2.java,v 1.6 2004/03/08 13:01:00 dmegginson Exp $ + +package org.xml.sax.ext; + +import org.xml.sax.Attributes; + + +/** + * SAX2 extension to augment the per-attribute information + * provided though {@link Attributes}. + * If an implementation supports this extension, the attributes + * provided in {@link org.xml.sax.ContentHandler#startElement + * ContentHandler.startElement() } will implement this interface, + * and the <em>http://xml.org/sax/features/use-attributes2</em> + * feature flag will have the value <em>true</em>. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * </blockquote> + * + * <p> XMLReader implementations are not required to support this + * information, and it is not part of core-only SAX2 distributions.</p> + * + * <p>Note that if an attribute was defaulted (<em>!isSpecified()</em>) + * it will of necessity also have been declared (<em>isDeclared()</em>) + * in the DTD. + * Similarly if an attribute's type is anything except CDATA, then it + * must have been declared. + * </p> + * + * @since SAX 2.0 (extensions 1.1 alpha) + * @author David Brownell + * @version TBS + */ +public interface Attributes2 extends Attributes +{ + /** + * 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); + + /** + * 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); + + /** + * Returns false unless the attribute was declared in the DTD. + * This helps distinguish two kinds of attributes that SAX reports + * as CDATA: ones that were declared (and hence are usually valid), + * and those that were not (and which are never valid). + * + * <p>Remember that since DTDs do not "understand" namespaces, the + * namespace URI associated with an attribute may not have come from + * the DTD. The declaration will have applied to the attribute's + * <em>qName</em>. + * + * @param uri The Namespace URI, or the empty string if + * the name has no Namespace URI. + * @param localName The attribute's local name. + * @return true if the attribute was declared in the DTD, + * false otherwise. + * @exception java.lang.IllegalArgumentException When the + * supplied names do not identify an attribute. + */ + public boolean isDeclared (String uri, String localName); + + /** + * 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); + + /** + * Returns true unless the attribute value was provided + * by DTD defaulting. + * + * <p>Remember that since DTDs do not "understand" namespaces, the + * namespace URI associated with an attribute may not have come from + * the DTD. The declaration will have applied to the attribute's + * <em>qName</em>. + * + * @param uri The Namespace URI, or the empty string if + * the name has no Namespace URI. + * @param localName The attribute's local name. + * @return true if the value was found in the XML text, + * false if the value was provided by DTD defaulting. + * @exception java.lang.IllegalArgumentException When the + * supplied names do not identify an attribute. + */ + public boolean isSpecified (String uri, String localName); + + /** + * 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); +} diff --git a/xml/src/main/java/org/xml/sax/ext/Attributes2Impl.java b/xml/src/main/java/org/xml/sax/ext/Attributes2Impl.java new file mode 100644 index 0000000..fc36805 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/Attributes2Impl.java @@ -0,0 +1,320 @@ +// Attributes2Impl.java - extended AttributesImpl +// http://www.saxproject.org +// Public Domain: no warranty. +// $Id: Attributes2Impl.java,v 1.5 2004/03/08 13:01:01 dmegginson Exp $ + +package org.xml.sax.ext; + +import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributesImpl; + + +/** + * SAX2 extension helper for additional Attributes information, + * implementing the {@link Attributes2} interface. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * </blockquote> + * + * <p>This is not part of core-only SAX2 distributions.</p> + * + * <p>The <em>specified</em> flag for each attribute will always + * be true, unless it has been set to false in the copy constructor + * or using {@link #setSpecified}. + * Similarly, the <em>declared</em> flag for each attribute will + * always be false, except for defaulted attributes (<em>specified</em> + * is false), non-CDATA attributes, or when it is set to true using + * {@link #setDeclared}. + * If you change an attribute's type by hand, you may need to modify + * its <em>declared</em> flag to match. + * </p> + * + * @since SAX 2.0 (extensions 1.1 alpha) + * @author David Brownell + * @version TBS + */ +public class Attributes2Impl extends AttributesImpl implements Attributes2 +{ + private boolean declared []; + private boolean specified []; + + + /** + * Construct a new, empty Attributes2Impl object. + */ + public Attributes2Impl () { + // BEGIN android-added + declared = new boolean[0]; + specified = new boolean[0]; + // END android-added + } + + + /** + * Copy an existing Attributes or Attributes2 object. + * If the object implements Attributes2, values of the + * <em>specified</em> and <em>declared</em> flags for each + * attribute are copied. + * Otherwise the flag values are defaulted to assume no DTD was used, + * unless there is evidence to the contrary (such as attributes with + * type other than CDATA, which must have been <em>declared</em>). + * + * <p>This constructor is especially useful inside a + * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p> + * + * @param atts The existing Attributes object. + */ + public Attributes2Impl (Attributes atts) + { + super (atts); + } + + + //////////////////////////////////////////////////////////////////// + // Implementation of Attributes2 + //////////////////////////////////////////////////////////////////// + + + /* + * Returns the current value of the attribute's "declared" flag. + */ + // javadoc mostly from interface + public boolean isDeclared (int index) + { + if (index < 0 || index >= getLength ()) + throw new ArrayIndexOutOfBoundsException ( + "No attribute at index: " + index); + return declared [index]; + } + + + /* + * Returns the current value of the attribute's "declared" flag. + */ + // javadoc mostly from interface + public boolean isDeclared (String uri, String localName) + { + int index = getIndex (uri, localName); + + if (index < 0) + throw new IllegalArgumentException ( + "No such attribute: local=" + localName + + ", namespace=" + uri); + return declared [index]; + } + + + /* + * Returns the current value of the attribute's "declared" flag. + */ + // javadoc mostly from interface + public boolean isDeclared (String qName) + { + int index = getIndex (qName); + + if (index < 0) + throw new IllegalArgumentException ( + "No such attribute: " + qName); + return declared [index]; + } + + + /** + * Returns the current value of an attribute's "specified" flag. + * + * @param index The attribute index (zero-based). + * @return current flag value + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not identify an attribute. + */ + public boolean isSpecified (int index) + { + if (index < 0 || index >= getLength ()) + throw new ArrayIndexOutOfBoundsException ( + "No attribute at index: " + index); + return specified [index]; + } + + + /** + * Returns the current value of an attribute's "specified" flag. + * + * @param uri The Namespace URI, or the empty string if + * the name has no Namespace URI. + * @param localName The attribute's local name. + * @return current flag value + * @exception java.lang.IllegalArgumentException When the + * supplied names do not identify an attribute. + */ + public boolean isSpecified (String uri, String localName) + { + int index = getIndex (uri, localName); + + if (index < 0) + throw new IllegalArgumentException ( + "No such attribute: local=" + localName + + ", namespace=" + uri); + return specified [index]; + } + + + /** + * Returns the current value of an attribute's "specified" flag. + * + * @param qName The XML qualified (prefixed) name. + * @return current flag value + * @exception java.lang.IllegalArgumentException When the + * supplied name does not identify an attribute. + */ + public boolean isSpecified (String qName) + { + int index = getIndex (qName); + + if (index < 0) + throw new IllegalArgumentException ( + "No such attribute: " + qName); + return specified [index]; + } + + + //////////////////////////////////////////////////////////////////// + // Manipulators + //////////////////////////////////////////////////////////////////// + + + /** + * Copy an entire Attributes object. The "specified" flags are + * assigned as true, and "declared" flags as false (except when + * an attribute's type is not CDATA), + * unless the object is an Attributes2 object. + * In that case those flag values are all copied. + * + * @param atts The attributes to copy. + * + * @see AttributesImpl#setAttributes + */ + public void setAttributes (Attributes atts) + { + int length = atts.getLength (); + + super.setAttributes (atts); + declared = new boolean [length]; + specified = new boolean [length]; + + if (atts instanceof Attributes2) { + Attributes2 a2 = (Attributes2) atts; + for (int i = 0; i < length; i++) { + declared [i] = a2.isDeclared (i); + specified [i] = a2.isSpecified (i); + } + } else { + for (int i = 0; i < length; i++) { + declared [i] = !"CDATA".equals (atts.getType (i)); + specified [i] = true; + } + } + } + + + /** + * Add an attribute to the end of the list, setting its + * "specified" flag to true. To set that flag's value + * to false, use {@link #setSpecified}. + * + * <p>Unless the attribute <em>type</em> is CDATA, this attribute + * is marked as being declared in the DTD. To set that flag's value + * to true for CDATA attributes, use {@link #setDeclared}. + * + * @param uri The Namespace URI, or the empty string if + * none is available or Namespace processing is not + * being performed. + * @param localName The local name, or the empty string if + * Namespace processing is not being performed. + * @param qName The qualified (prefixed) name, or the empty string + * if qualified names are not available. + * @param type The attribute type as a string. + * @param value The attribute value. + * + * @see AttributesImpl#addAttribute + */ + public void addAttribute (String uri, String localName, String qName, + String type, String value) + { + super.addAttribute (uri, localName, qName, type, value); + + int length = getLength (); + + // BEGIN android-changed + if (length > specified.length) { + // END android-changed + boolean newFlags []; + + newFlags = new boolean [length]; + System.arraycopy (declared, 0, newFlags, 0, declared.length); + declared = newFlags; + + newFlags = new boolean [length]; + System.arraycopy (specified, 0, newFlags, 0, specified.length); + specified = newFlags; + } + + specified [length - 1] = true; + declared [length - 1] = !"CDATA".equals (type); + } + + + // javadoc entirely from superclass + public void removeAttribute (int index) + { + int origMax = getLength () - 1; + + super.removeAttribute (index); + if (index != origMax) { + System.arraycopy (declared, index + 1, declared, index, + origMax - index); + System.arraycopy (specified, index + 1, specified, index, + origMax - index); + } + } + + + /** + * Assign a value to the "declared" flag of a specific attribute. + * This is normally needed only for attributes of type CDATA, + * including attributes whose type is changed to or from CDATA. + * + * @param index The index of the attribute (zero-based). + * @param value The desired flag value. + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not identify an attribute. + * @see #setType + */ + public void setDeclared (int index, boolean value) + { + if (index < 0 || index >= getLength ()) + throw new ArrayIndexOutOfBoundsException ( + "No attribute at index: " + index); + declared [index] = value; + } + + + /** + * Assign a value to the "specified" flag of a specific attribute. + * This is the only way this flag can be cleared, except clearing + * by initialization with the copy constructor. + * + * @param index The index of the attribute (zero-based). + * @param value The desired flag value. + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not identify an attribute. + */ + public void setSpecified (int index, boolean value) + { + if (index < 0 || index >= getLength ()) + throw new ArrayIndexOutOfBoundsException ( + "No attribute at index: " + index); + specified [index] = value; + } +} diff --git a/xml/src/main/java/org/xml/sax/ext/DeclHandler.java b/xml/src/main/java/org/xml/sax/ext/DeclHandler.java new file mode 100644 index 0000000..26471f3 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/DeclHandler.java @@ -0,0 +1,146 @@ +// DeclHandler.java - Optional handler for DTD declaration events. +// http://www.saxproject.org +// Public Domain: no warranty. +// $Id: DeclHandler.java,v 1.6 2004/04/22 13:28:49 dmegginson Exp $ + +package org.xml.sax.ext; + +import org.xml.sax.SAXException; + + +/** + * SAX2 extension handler for DTD declaration events. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This is an optional extension handler for SAX2 to provide more + * complete information about DTD declarations in an XML document. + * XML readers are not required to recognize this handler, and it + * is not part of core-only SAX2 distributions.</p> + * + * <p>Note that data-related DTD declarations (unparsed entities and + * notations) are already reported through the {@link + * org.xml.sax.DTDHandler DTDHandler} interface.</p> + * + * <p>If you are using the declaration handler together with a lexical + * handler, all of the events will occur between the + * {@link org.xml.sax.ext.LexicalHandler#startDTD startDTD} and the + * {@link org.xml.sax.ext.LexicalHandler#endDTD endDTD} events.</p> + * + * <p>To set the DeclHandler for an XML reader, use the + * {@link org.xml.sax.XMLReader#setProperty setProperty} method + * with the property name + * <code>http://xml.org/sax/properties/declaration-handler</code> + * and an object implementing this interface (or null) as the value. + * If the reader does not report declaration events, it will throw a + * {@link org.xml.sax.SAXNotRecognizedException SAXNotRecognizedException} + * when you attempt to register the handler.</p> + * + * @since SAX 2.0 (extensions 1.0) + * @author David Megginson + * @version 2.0.1 (sax2r2) + */ +public interface DeclHandler +{ + + /** + * Report an element type declaration. + * + * <p>The content model will consist of the string "EMPTY", the + * string "ANY", or a parenthesised group, optionally followed + * by an occurrence indicator. The model will be normalized so + * that all parameter entities are fully resolved and all whitespace + * is removed,and will include the enclosing parentheses. Other + * normalization (such as removing redundant parentheses or + * simplifying occurrence indicators) is at the discretion of the + * parser.</p> + * + * @param name The element type name. + * @param model The content model as a normalized string. + * @exception SAXException The application may raise an exception. + */ + public abstract void elementDecl (String name, String model) + throws SAXException; + + + /** + * Report an attribute type declaration. + * + * <p>Only the effective (first) declaration for an attribute will + * be reported. The type will be one of the strings "CDATA", + * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", + * "ENTITIES", a parenthesized token group with + * the separator "|" and all whitespace removed, or the word + * "NOTATION" followed by a space followed by a parenthesized + * token group with all whitespace removed.</p> + * + * <p>The value will be the value as reported to applications, + * appropriately normalized and with entity and character + * references expanded. </p> + * + * @param eName The name of the associated element. + * @param aName The name of the attribute. + * @param type A string representing the attribute type. + * @param mode A string representing the attribute defaulting mode + * ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if + * none of these applies. + * @param value A string representing the attribute's default value, + * or null if there is none. + * @exception SAXException The application may raise an exception. + */ + public abstract void attributeDecl (String eName, + String aName, + String type, + String mode, + String value) + throws SAXException; + + + /** + * Report an internal entity declaration. + * + * <p>Only the effective (first) declaration for each entity + * will be reported. All parameter entities in the value + * will be expanded, but general entities will not.</p> + * + * @param name The name of the entity. If it is a parameter + * entity, the name will begin with '%'. + * @param value The replacement text of the entity. + * @exception SAXException The application may raise an exception. + * @see #externalEntityDecl + * @see org.xml.sax.DTDHandler#unparsedEntityDecl + */ + public abstract void internalEntityDecl (String name, String value) + throws SAXException; + + + /** + * Report a parsed external entity declaration. + * + * <p>Only the effective (first) declaration for each entity + * will be reported.</p> + * + * <p>If the system identifier is a URL, the parser must resolve it + * fully before passing it to the application.</p> + * + * @param name The name of the entity. If it is a parameter + * entity, the name will begin with '%'. + * @param publicId The entity's public identifier, or null if none + * was given. + * @param systemId The entity's system identifier. + * @exception SAXException The application may raise an exception. + * @see #internalEntityDecl + * @see org.xml.sax.DTDHandler#unparsedEntityDecl + */ + public abstract void externalEntityDecl (String name, String publicId, + String systemId) + throws SAXException; + +} + +// end of DeclHandler.java diff --git a/xml/src/main/java/org/xml/sax/ext/DefaultHandler2.java b/xml/src/main/java/org/xml/sax/ext/DefaultHandler2.java new file mode 100644 index 0000000..f26564f --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/DefaultHandler2.java @@ -0,0 +1,185 @@ +// DefaultHandler2.java - extended DefaultHandler +// http://www.saxproject.org +// Public Domain: no warranty. +// $Id: DefaultHandler2.java,v 1.3 2002/01/12 19:04:19 dbrownell Exp $ + +package org.xml.sax.ext; + +import java.io.IOException; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + + +/** + * This class extends the SAX2 base handler class to support the + * SAX2 {@link LexicalHandler}, {@link DeclHandler}, and + * {@link EntityResolver2} extensions. Except for overriding the + * original SAX1 {@link DefaultHandler#resolveEntity resolveEntity()} + * method the added handler methods just return. Subclassers may + * override everything on a method-by-method basis. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * </blockquote> + * + * <p> <em>Note:</em> this class might yet learn that the + * <em>ContentHandler.setDocumentLocator()</em> call might be passed a + * {@link Locator2} object, and that the + * <em>ContentHandler.startElement()</em> call might be passed a + * {@link Attributes2} object. + * + * @since SAX 2.0 (extensions 1.1 alpha) + * @author David Brownell + * @version TBS + */ +public class DefaultHandler2 extends DefaultHandler + implements LexicalHandler, DeclHandler, EntityResolver2 +{ + /** Constructs a handler which ignores all parsing events. */ + public DefaultHandler2 () { } + + + // SAX2 ext-1.0 LexicalHandler + + public void startCDATA () + throws SAXException + {} + + public void endCDATA () + throws SAXException + {} + + public void startDTD (String name, String publicId, String systemId) + throws SAXException + {} + + public void endDTD () + throws SAXException + {} + + public void startEntity (String name) + throws SAXException + {} + + public void endEntity (String name) + throws SAXException + {} + + public void comment (char ch [], int start, int length) + throws SAXException + { } + + + // SAX2 ext-1.0 DeclHandler + + public void attributeDecl (String eName, String aName, + String type, String mode, String value) + throws SAXException + {} + + public void elementDecl (String name, String model) + throws SAXException + {} + + public void externalEntityDecl (String name, + String publicId, String systemId) + throws SAXException + {} + + public void internalEntityDecl (String name, String value) + throws SAXException + {} + + // SAX2 ext-1.1 EntityResolver2 + + /** + * Tells the parser that if no external subset has been declared + * in the document text, none should be used. + * + * @param name Identifies the document root element. This name comes + * from a DOCTYPE declaration (where available) or from the actual + * root element. The parameter is ignored. + * @param baseURI The document's base URI, serving as an additional + * hint for selecting the external subset. This is always an absolute + * URI, unless it is null because the XMLReader was given an InputSource + * without one. The parameter is ignored. + * + * @return null (always). + * + * @exception SAXException Any SAX exception, possibly wrapping + * another exception. + * @exception IOException Probably indicating a failure to create + * a new InputStream or Reader, or an illegal URL. + */ + public InputSource getExternalSubset (String name, String baseURI) + throws SAXException, IOException + { return null; } + + /** + * Tells the parser to resolve the systemId against the baseURI + * and read the entity text from that resulting absolute URI. + * Note that because the older + * {@link DefaultHandler#resolveEntity DefaultHandler.resolveEntity()}, + * method is overridden to call this one, this method may sometimes + * be invoked with null <em>name</em> and <em>baseURI</em>, and + * with the <em>systemId</em> already absolutized. + * + * @param name Identifies the external entity being resolved. + * Either "[dtd]" for the external subset, or a name starting + * with "%" to indicate a parameter entity, or else the name of + * a general entity. This is never null when invoked by a SAX2 + * parser. + * @param publicId The public identifier of the external entity being + * referenced (normalized as required by the XML specification), or + * null if none was supplied. + * @param baseURI The URI with respect to which relative systemIDs + * are interpreted. This is always an absolute URI, unless it is + * null (likely because the XMLReader was given an InputSource without + * one). This URI is defined by the XML specification to be the one + * associated with the "<" starting the relevant declaration. + * @param systemId The system identifier of the external entity + * being referenced; either a relative or absolute URI. + * This is never null when invoked by a SAX2 parser; only declared + * entities, and any external subset, are resolved by such parsers. + * + * @return An InputSource object describing the new input source. + * + * @exception SAXException Any SAX exception, possibly wrapping + * another exception. + * @exception IOException Probably indicating a failure to create + * a new InputStream or Reader, or an illegal URL. + */ + public InputSource resolveEntity (String name, String publicId, + String baseURI, String systemId) + throws SAXException, IOException + { return null; } + + // SAX1 EntityResolver + + /** + * Invokes + * {@link EntityResolver2#resolveEntity EntityResolver2.resolveEntity()} + * with null entity name and base URI. + * You only need to override that method to use this class. + * + * @param publicId The public identifier of the external entity being + * referenced (normalized as required by the XML specification), or + * null if none was supplied. + * @param systemId The system identifier of the external entity + * being referenced; either a relative or absolute URI. + * This is never null when invoked by a SAX2 parser; only declared + * entities, and any external subset, are resolved by such parsers. + * + * @return An InputSource object describing the new input source. + * + * @exception SAXException Any SAX exception, possibly wrapping + * another exception. + * @exception IOException Probably indicating a failure to create + * a new InputStream or Reader, or an illegal URL. + */ + public InputSource resolveEntity (String publicId, String systemId) + throws SAXException, IOException + { return resolveEntity (null, publicId, null, systemId); } +} diff --git a/xml/src/main/java/org/xml/sax/ext/EntityResolver2.java b/xml/src/main/java/org/xml/sax/ext/EntityResolver2.java new file mode 100644 index 0000000..5437a9b --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/EntityResolver2.java @@ -0,0 +1,197 @@ +// EntityResolver2.java - Extended SAX entity resolver. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: EntityResolver2.java,v 1.2 2002/01/12 19:20:08 dbrownell Exp $ + +package org.xml.sax.ext; + +import java.io.IOException; + +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.SAXException; + + +/** + * Extended interface for mapping external entity references to input + * sources, or providing a missing external subset. The + * {@link XMLReader#setEntityResolver XMLReader.setEntityResolver()} method + * is used to provide implementations of this interface to parsers. + * When a parser uses the methods in this interface, the + * {@link EntityResolver2#resolveEntity EntityResolver2.resolveEntity()} + * method (in this interface) is used <em>instead of</em> the older (SAX 1.0) + * {@link EntityResolver#resolveEntity EntityResolver.resolveEntity()} method. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * </blockquote> + * + * <p>If a SAX application requires the customized handling which this + * interface defines for external entities, it must ensure that it uses + * an XMLReader with the + * <em>http://xml.org/sax/features/use-entity-resolver2</em> feature flag + * set to <em>true</em> (which is its default value when the feature is + * recognized). If that flag is unrecognized, or its value is false, + * or the resolver does not implement this interface, then only the + * {@link EntityResolver} method will be used. + * </p> + * + * <p>That supports three categories of application that modify entity + * resolution. <em>Old Style</em> applications won't know about this interface; + * they will provide an EntityResolver. + * <em>Transitional Mode</em> provide an EntityResolver2 and automatically + * get the benefit of its methods in any systems (parsers or other tools) + * supporting it, due to polymorphism. + * Both <em>Old Style</em> and <em>Transitional Mode</em> applications will + * work with any SAX2 parser. + * <em>New style</em> applications will fail to run except on SAX2 parsers + * that support this particular feature. + * They will insist that feature flag have a value of "true", and the + * EntityResolver2 implementation they provide might throw an exception + * if the original SAX 1.0 style entity resolution method is invoked. + * </p> + * + * @see org.xml.sax.XMLReader#setEntityResolver + * + * @since SAX 2.0 (extensions 1.1 alpha) + * @author David Brownell + * @version TBD + */ +public interface EntityResolver2 extends EntityResolver +{ + /** + * Allows applications to provide an external subset for documents + * that don't explicitly define one. Documents with DOCTYPE declarations + * that omit an external subset can thus augment the declarations + * available for validation, entity processing, and attribute processing + * (normalization, defaulting, and reporting types including ID). + * This augmentation is reported + * through the {@link LexicalHandler#startDTD startDTD()} method as if + * the document text had originally included the external subset; + * this callback is made before any internal subset data or errors + * are reported.</p> + * + * <p>This method can also be used with documents that have no DOCTYPE + * declaration. When the root element is encountered, + * but no DOCTYPE declaration has been seen, this method is + * invoked. If it returns a value for the external subset, that root + * element is declared to be the root element, giving the effect of + * splicing a DOCTYPE declaration at the end the prolog of a document + * that could not otherwise be valid. The sequence of parser callbacks + * in that case logically resembles this:</p> + * + * <pre> + * ... comments and PIs from the prolog (as usual) + * startDTD ("rootName", source.getPublicId (), source.getSystemId ()); + * startEntity ("[dtd]"); + * ... declarations, comments, and PIs from the external subset + * endEntity ("[dtd]"); + * endDTD (); + * ... then the rest of the document (as usual) + * startElement (..., "rootName", ...); + * </pre> + * + * <p>Note that the InputSource gets no further resolution. + * Implementations of this method may wish to invoke + * {@link #resolveEntity resolveEntity()} to gain benefits such as use + * of local caches of DTD entities. Also, this method will never be + * used by a (non-validating) processor that is not including external + * parameter entities. </p> + * + * <p>Uses for this method include facilitating data validation when + * interoperating with XML processors that would always require + * undesirable network accesses for external entities, or which for + * other reasons adopt a "no DTDs" policy. + * Non-validation motives include forcing documents to include DTDs so + * that attributes are handled consistently. + * For example, an XPath processor needs to know which attibutes have + * type "ID" before it can process a widely used type of reference.</p> + * + * <p><strong>Warning:</strong> Returning an external subset modifies + * the input document. By providing definitions for general entities, + * it can make a malformed document appear to be well formed. + * </p> + * + * @param name Identifies the document root element. This name comes + * from a DOCTYPE declaration (where available) or from the actual + * root element. + * @param baseURI The document's base URI, serving as an additional + * hint for selecting the external subset. This is always an absolute + * URI, unless it is null because the XMLReader was given an InputSource + * without one. + * + * @return An InputSource object describing the new external subset + * to be used by the parser, or null to indicate that no external + * subset is provided. + * + * @exception SAXException Any SAX exception, possibly wrapping + * another exception. + * @exception IOException Probably indicating a failure to create + * a new InputStream or Reader, or an illegal URL. + */ + public InputSource getExternalSubset (String name, String baseURI) + throws SAXException, IOException; + + /** + * Allows applications to map references to external entities into input + * sources, or tell the parser it should use conventional URI resolution. + * This method is only called for external entities which have been + * properly declared. + * This method provides more flexibility than the {@link EntityResolver} + * interface, supporting implementations of more complex catalogue + * schemes such as the one defined by the <a href= + "http://www.oasis-open.org/committees/entity/spec-2001-08-06.html" + >OASIS XML Catalogs</a> specification.</p> + * + * <p>Parsers configured to use this resolver method will call it + * to determine the input source to use for any external entity + * being included because of a reference in the XML text. + * That excludes the document entity, and any external entity returned + * by {@link #getExternalSubset getExternalSubset()}. + * When a (non-validating) processor is configured not to include + * a class of entities (parameter or general) through use of feature + * flags, this method is not invoked for such entities. </p> + * + * <p>Note that the entity naming scheme used here is the same one + * used in the {@link LexicalHandler}, or in the {@link + org.xml.sax.ContentHandler#skippedEntity + ContentHandler.skippedEntity()} + * method. </p> + * + * @param name Identifies the external entity being resolved. + * Either "[dtd]" for the external subset, or a name starting + * with "%" to indicate a parameter entity, or else the name of + * a general entity. This is never null when invoked by a SAX2 + * parser. + * @param publicId The public identifier of the external entity being + * referenced (normalized as required by the XML specification), or + * null if none was supplied. + * @param baseURI The URI with respect to which relative systemIDs + * are interpreted. This is always an absolute URI, unless it is + * null (likely because the XMLReader was given an InputSource without + * one). This URI is defined by the XML specification to be the one + * associated with the "<" starting the relevant declaration. + * @param systemId The system identifier of the external entity + * being referenced; either a relative or absolute URI. + * This is never null when invoked by a SAX2 parser; only declared + * entities, and any external subset, are resolved by such parsers. + * + * @return An InputSource object describing the new input source to + * be used by the parser. Returning null directs the parser to + * resolve the system ID against the base URI and open a connection + * to resulting URI. + * + * @exception SAXException Any SAX exception, possibly wrapping + * another exception. + * @exception IOException Probably indicating a failure to create + * a new InputStream or Reader, or an illegal URL. + */ + public InputSource resolveEntity ( + String name, + String publicId, + String baseURI, + String systemId + ) throws SAXException, IOException; +} diff --git a/xml/src/main/java/org/xml/sax/ext/LexicalHandler.java b/xml/src/main/java/org/xml/sax/ext/LexicalHandler.java new file mode 100644 index 0000000..e551b61 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/LexicalHandler.java @@ -0,0 +1,212 @@ +// LexicalHandler.java - optional handler for lexical parse events. +// http://www.saxproject.org +// Public Domain: no warranty. +// $Id: LexicalHandler.java,v 1.5 2002/01/30 21:00:44 dbrownell Exp $ + +package org.xml.sax.ext; + +import org.xml.sax.SAXException; + +/** + * SAX2 extension handler for lexical events. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This is an optional extension handler for SAX2 to provide + * lexical information about an XML document, such as comments + * and CDATA section boundaries. + * XML readers are not required to recognize this handler, and it + * is not part of core-only SAX2 distributions.</p> + * + * <p>The events in the lexical handler apply to the entire document, + * not just to the document element, and all lexical handler events + * must appear between the content handler's startDocument and + * endDocument events.</p> + * + * <p>To set the LexicalHandler for an XML reader, use the + * {@link org.xml.sax.XMLReader#setProperty setProperty} method + * with the property name + * <code>http://xml.org/sax/properties/lexical-handler</code> + * and an object implementing this interface (or null) as the value. + * If the reader does not report lexical events, it will throw a + * {@link org.xml.sax.SAXNotRecognizedException SAXNotRecognizedException} + * when you attempt to register the handler.</p> + * + * @since SAX 2.0 (extensions 1.0) + * @author David Megginson + * @version 2.0.1 (sax2r2) + */ +public interface LexicalHandler +{ + + /** + * Report the start of DTD declarations, if any. + * + * <p>This method is intended to report the beginning of the + * DOCTYPE declaration; if the document has no DOCTYPE declaration, + * this method will not be invoked.</p> + * + * <p>All declarations reported through + * {@link org.xml.sax.DTDHandler DTDHandler} or + * {@link org.xml.sax.ext.DeclHandler DeclHandler} events must appear + * between the startDTD and {@link #endDTD endDTD} events. + * Declarations are assumed to belong to the internal DTD subset + * unless they appear between {@link #startEntity startEntity} + * and {@link #endEntity endEntity} events. Comments and + * processing instructions from the DTD should also be reported + * between the startDTD and endDTD events, in their original + * order of (logical) occurrence; they are not required to + * appear in their correct locations relative to DTDHandler + * or DeclHandler events, however.</p> + * + * <p>Note that the start/endDTD events will appear within + * the start/endDocument events from ContentHandler and + * before the first + * {@link org.xml.sax.ContentHandler#startElement startElement} + * event.</p> + * + * @param name The document type name. + * @param publicId The declared public identifier for the + * external DTD subset, or null if none was declared. + * @param systemId The declared system identifier for the + * external DTD subset, or null if none was declared. + * (Note that this is not resolved against the document + * base URI.) + * @exception SAXException The application may raise an + * exception. + * @see #endDTD + * @see #startEntity + */ + public abstract void startDTD (String name, String publicId, + String systemId) + throws SAXException; + + + /** + * Report the end of DTD declarations. + * + * <p>This method is intended to report the end of the + * DOCTYPE declaration; if the document has no DOCTYPE declaration, + * this method will not be invoked.</p> + * + * @exception SAXException The application may raise an exception. + * @see #startDTD + */ + public abstract void endDTD () + throws SAXException; + + + /** + * Report the beginning of some internal and external XML entities. + * + * <p>The reporting of parameter entities (including + * the external DTD subset) is optional, and SAX2 drivers that + * report LexicalHandler events may not implement it; you can use the + * <code + * >http://xml.org/sax/features/lexical-handler/parameter-entities</code> + * feature to query or control the reporting of parameter entities.</p> + * + * <p>General entities are reported with their regular names, + * parameter entities have '%' prepended to their names, and + * the external DTD subset has the pseudo-entity name "[dtd]".</p> + * + * <p>When a SAX2 driver is providing these events, all other + * events must be properly nested within start/end entity + * events. There is no additional requirement that events from + * {@link org.xml.sax.ext.DeclHandler DeclHandler} or + * {@link org.xml.sax.DTDHandler DTDHandler} be properly ordered.</p> + * + * <p>Note that skipped entities will be reported through the + * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity} + * event, which is part of the ContentHandler interface.</p> + * + * <p>Because of the streaming event model that SAX uses, some + * entity boundaries cannot be reported under any + * circumstances:</p> + * + * <ul> + * <li>general entities within attribute values</li> + * <li>parameter entities within declarations</li> + * </ul> + * + * <p>These will be silently expanded, with no indication of where + * the original entity boundaries were.</p> + * + * <p>Note also that the boundaries of character references (which + * are not really entities anyway) are not reported.</p> + * + * <p>All start/endEntity events must be properly nested. + * + * @param name The name of the entity. If it is a parameter + * entity, the name will begin with '%', and if it is the + * external DTD subset, it will be "[dtd]". + * @exception SAXException The application may raise an exception. + * @see #endEntity + * @see org.xml.sax.ext.DeclHandler#internalEntityDecl + * @see org.xml.sax.ext.DeclHandler#externalEntityDecl + */ + public abstract void startEntity (String name) + throws SAXException; + + + /** + * Report the end of an entity. + * + * @param name The name of the entity that is ending. + * @exception SAXException The application may raise an exception. + * @see #startEntity + */ + public abstract void endEntity (String name) + throws SAXException; + + + /** + * Report the start of a CDATA section. + * + * <p>The contents of the CDATA section will be reported through + * the regular {@link org.xml.sax.ContentHandler#characters + * characters} event; this event is intended only to report + * the boundary.</p> + * + * @exception SAXException The application may raise an exception. + * @see #endCDATA + */ + public abstract void startCDATA () + throws SAXException; + + + /** + * Report the end of a CDATA section. + * + * @exception SAXException The application may raise an exception. + * @see #startCDATA + */ + public abstract void endCDATA () + throws SAXException; + + + /** + * Report an XML comment anywhere in the document. + * + * <p>This callback will be used for comments inside or outside the + * document element, including comments in the external DTD + * subset (if read). Comments in the DTD must be properly + * nested inside start/endDTD and start/endEntity events (if + * used).</p> + * + * @param ch An array holding the characters in the comment. + * @param start The starting position in the array. + * @param length The number of characters to use from the array. + * @exception SAXException The application may raise an exception. + */ + public abstract void comment (char ch[], int start, int length) + throws SAXException; + +} + +// end of LexicalHandler.java diff --git a/xml/src/main/java/org/xml/sax/ext/Locator2.java b/xml/src/main/java/org/xml/sax/ext/Locator2.java new file mode 100644 index 0000000..6de9a16 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/Locator2.java @@ -0,0 +1,75 @@ +// Locator2.java - extended Locator +// http://www.saxproject.org +// Public Domain: no warranty. +// $Id: Locator2.java,v 1.5 2004/03/17 14:30:10 dmegginson Exp $ + +package org.xml.sax.ext; + +import org.xml.sax.Locator; + + +/** + * SAX2 extension to augment the entity information provided + * though a {@link Locator}. + * If an implementation supports this extension, the Locator + * provided in {@link org.xml.sax.ContentHandler#setDocumentLocator + * ContentHandler.setDocumentLocator() } will implement this + * interface, and the + * <em>http://xml.org/sax/features/use-locator2</em> feature + * flag will have the value <em>true</em>. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * </blockquote> + * + * <p> XMLReader implementations are not required to support this + * information, and it is not part of core-only SAX2 distributions.</p> + * + * @since SAX 2.0 (extensions 1.1 alpha) + * @author David Brownell + * @version TBS + */ +public interface Locator2 extends Locator +{ + /** + * Returns the version of XML used for the entity. This will + * normally be the identifier from the current entity's + * <em><?xml version='...' ...?></em> declaration, + * or be defaulted by the parser. + * + * @return Identifier for the XML version being used to interpret + * the entity's text, or null if that information is not yet + * available in the current parsing state. + */ + public String getXMLVersion (); + + /** + * Returns the name of the character encoding for the entity. + * If the encoding was declared externally (for example, in a MIME + * Content-Type header), that will be the name returned. Else if there + * was an <em><?xml ...encoding='...'?></em> declaration at + * the start of the document, that encoding name will be returned. + * Otherwise the encoding will been inferred (normally to be UTF-8, or + * some UTF-16 variant), and that inferred name will be returned. + * + * <p>When an {@link org.xml.sax.InputSource InputSource} is used + * to provide an entity's character stream, this method returns the + * encoding provided in that input stream. + * + * <p> Note that some recent W3C specifications require that text + * in some encodings be normalized, using Unicode Normalization + * Form C, before processing. Such normalization must be performed + * by applications, and would normally be triggered based on the + * value returned by this method. + * + * <p> Encoding names may be those used by the underlying JVM, + * and comparisons should be case-insensitive. + * + * @return Name of the character encoding being used to interpret + * * the entity's text, or null if this was not provided for a * + * character stream passed through an InputSource or is otherwise + * not yet available in the current parsing state. + */ + public String getEncoding (); +} diff --git a/xml/src/main/java/org/xml/sax/ext/Locator2Impl.java b/xml/src/main/java/org/xml/sax/ext/Locator2Impl.java new file mode 100644 index 0000000..91f912a --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/Locator2Impl.java @@ -0,0 +1,105 @@ +// Locator2Impl.java - extended LocatorImpl +// http://www.saxproject.org +// Public Domain: no warranty. +// $Id: Locator2Impl.java,v 1.3 2004/04/26 17:34:35 dmegginson Exp $ + +package org.xml.sax.ext; + +import org.xml.sax.Locator; +import org.xml.sax.helpers.LocatorImpl; + + +/** + * SAX2 extension helper for holding additional Entity information, + * implementing the {@link Locator2} interface. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * </blockquote> + * + * <p> This is not part of core-only SAX2 distributions.</p> + * + * @since SAX 2.0.2 + * @author David Brownell + * @version TBS + */ +public class Locator2Impl extends LocatorImpl implements Locator2 +{ + private String encoding; + private String version; + + + /** + * Construct a new, empty Locator2Impl object. + * This will not normally be useful, since the main purpose + * of this class is to make a snapshot of an existing Locator. + */ + public Locator2Impl () { } + + /** + * Copy an existing Locator or Locator2 object. + * If the object implements Locator2, values of the + * <em>encoding</em> and <em>version</em>strings are copied, + * otherwise they set to <em>null</em>. + * + * @param locator The existing Locator object. + */ + public Locator2Impl (Locator locator) + { + super (locator); + if (locator instanceof Locator2) { + Locator2 l2 = (Locator2) locator; + + version = l2.getXMLVersion (); + encoding = l2.getEncoding (); + } + } + + //////////////////////////////////////////////////////////////////// + // Locator2 method implementations + //////////////////////////////////////////////////////////////////// + + /** + * Returns the current value of the version property. + * + * @return the current value of the version property. + * + * @see #setXMLVersion + */ + public String getXMLVersion () + { return version; } + + /** + * Returns the current value of the encoding property. + * + * @return the current value of the encoding property. + * + * @see #setEncoding + */ + public String getEncoding () + { return encoding; } + + + //////////////////////////////////////////////////////////////////// + // Setters + //////////////////////////////////////////////////////////////////// + + /** + * Assigns the current value of the version property. + * + * @param version the new "version" value + * @see #getXMLVersion + */ + public void setXMLVersion (String version) + { this.version = version; } + + /** + * Assigns the current value of the encoding property. + * + * @param encoding the new "encoding" value + * @see #getEncoding + */ + public void setEncoding (String encoding) + { this.encoding = encoding; } +} diff --git a/xml/src/main/java/org/xml/sax/ext/package.html b/xml/src/main/java/org/xml/sax/ext/package.html new file mode 100644 index 0000000..9b79d77 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/ext/package.html @@ -0,0 +1,48 @@ +<HTML><HEAD> +<!-- $Id: package.html,v 1.8 2002/01/30 21:00:44 dbrownell Exp $ --> +</HEAD><BODY> + +<p> +This package contains interfaces to SAX2 facilities that +conformant SAX drivers won't necessarily support. + +<p>See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> +for more information about SAX.</p> + +<p> This package is independent of the SAX2 core, though the functionality +exposed generally needs to be implemented within a parser core. +That independence has several consequences:</p> + +<ul> + +<li>SAX2 drivers are <em>not</em> required to recognize these handlers. +</li> + +<li>You cannot assume that the class files will be present in every SAX2 +installation.</li> + +<li>This package may be updated independently of SAX2 (i.e. new +handlers and classes may be added without updating SAX2 itself).</li> + +<li>The new handlers are not implemented by the SAX2 +<code>org.xml.sax.helpers.DefaultHandler</code> or +<code>org.xml.sax.helpers.XMLFilterImpl</code> classes. +You can subclass these if you need such behavior, or +use the helper classes found here.</li> + +<li>The handlers need to be registered differently than core SAX2 +handlers.</li> + +</ul> + +<p>This package, SAX2-ext, is a standardized extension to SAX2. It is +designed both to allow SAX parsers to pass certain types of information +to applications, and to serve as a simple model for other SAX2 parser +extension packages. Not all such extension packages should need to +be recognized directly by parsers, however. +As an example, most validation systems can be cleanly layered on top +of parsers supporting the standardized SAX2 interfaces. </p> + +@since Android 1.0 + +</BODY></HTML> diff --git a/xml/src/main/java/org/xml/sax/helpers/AttributeListImpl.java b/xml/src/main/java/org/xml/sax/helpers/AttributeListImpl.java new file mode 100644 index 0000000..fb4aee3 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/AttributeListImpl.java @@ -0,0 +1,314 @@ +// SAX default implementation for AttributeList. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: AttributeListImpl.java,v 1.6 2002/01/30 20:52:22 dbrownell Exp $ + +package org.xml.sax.helpers; + +import org.xml.sax.AttributeList; + +import java.util.Vector; + + +/** + * Default implementation for AttributeList. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>AttributeList implements the deprecated SAX1 {@link + * org.xml.sax.AttributeList AttributeList} interface, and has been + * replaced by the new SAX2 {@link org.xml.sax.helpers.AttributesImpl + * AttributesImpl} interface.</p> + * + * <p>This class provides a convenience implementation of the SAX + * {@link org.xml.sax.AttributeList AttributeList} interface. This + * implementation is useful both for SAX parser writers, who can use + * it to provide attributes to the application, and for SAX application + * writers, who can use it to create a persistent copy of an element's + * attribute specifications:</p> + * + * <pre> + * private AttributeList myatts; + * + * public void startElement (String name, AttributeList atts) + * { + * // create a persistent copy of the attribute list + * // for use outside this method + * myatts = new AttributeListImpl(atts); + * [...] + * } + * </pre> + * + * <p>Please note that SAX parsers are not required to use this + * class to provide an implementation of AttributeList; it is + * supplied only as an optional convenience. In particular, + * parser writers are encouraged to invent more efficient + * implementations.</p> + * + * @deprecated This class implements a deprecated interface, + * {@link org.xml.sax.AttributeList AttributeList}; + * that interface has been replaced by + * {@link org.xml.sax.Attributes Attributes}, + * which is implemented in the + * {@link org.xml.sax.helpers.AttributesImpl + * AttributesImpl} helper class. + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.AttributeList + * @see org.xml.sax.DocumentHandler#startElement + */ +public class AttributeListImpl implements AttributeList +{ + + /** + * Create an empty attribute list. + * + * <p>This constructor is most useful for parser writers, who + * will use it to create a single, reusable attribute list that + * can be reset with the clear method between elements.</p> + * + * @see #addAttribute + * @see #clear + */ + public AttributeListImpl () + { + } + + + /** + * Construct a persistent copy of an existing attribute list. + * + * <p>This constructor is most useful for application writers, + * who will use it to create a persistent copy of an existing + * attribute list.</p> + * + * @param atts The attribute list to copy + * @see org.xml.sax.DocumentHandler#startElement + */ + public AttributeListImpl (AttributeList atts) + { + setAttributeList(atts); + } + + + + //////////////////////////////////////////////////////////////////// + // Methods specific to this class. + //////////////////////////////////////////////////////////////////// + + + /** + * Set the attribute list, discarding previous contents. + * + * <p>This method allows an application writer to reuse an + * attribute list easily.</p> + * + * @param atts The attribute list to copy. + */ + public void setAttributeList (AttributeList atts) + { + int count = atts.getLength(); + + clear(); + + for (int i = 0; i < count; i++) { + addAttribute(atts.getName(i), atts.getType(i), atts.getValue(i)); + } + } + + + /** + * Add an attribute to an attribute list. + * + * <p>This method is provided for SAX parser writers, to allow them + * to build up an attribute list incrementally before delivering + * it to the application.</p> + * + * @param name The attribute name. + * @param type The attribute type ("NMTOKEN" for an enumeration). + * @param value The attribute value (must not be null). + * @see #removeAttribute + * @see org.xml.sax.DocumentHandler#startElement + */ + public void addAttribute (String name, String type, String value) + { + names.addElement(name); + types.addElement(type); + values.addElement(value); + } + + + /** + * Remove an attribute from the list. + * + * <p>SAX application writers can use this method to filter an + * attribute out of an AttributeList. Note that invoking this + * method will change the length of the attribute list and + * some of the attribute's indices.</p> + * + * <p>If the requested attribute is not in the list, this is + * a no-op.</p> + * + * @param name The attribute name. + * @see #addAttribute + */ + public void removeAttribute (String name) + { + int i = names.indexOf(name); + + if (i >= 0) { + names.removeElementAt(i); + types.removeElementAt(i); + values.removeElementAt(i); + } + } + + + /** + * Clear the attribute list. + * + * <p>SAX parser writers can use this method to reset the attribute + * list between DocumentHandler.startElement events. Normally, + * it will make sense to reuse the same AttributeListImpl object + * rather than allocating a new one each time.</p> + * + * @see org.xml.sax.DocumentHandler#startElement + */ + public void clear () + { + names.removeAllElements(); + types.removeAllElements(); + values.removeAllElements(); + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.AttributeList + //////////////////////////////////////////////////////////////////// + + + /** + * Return the number of attributes in the list. + * + * @return The number of attributes in the list. + * @see org.xml.sax.AttributeList#getLength + */ + public int getLength () + { + return names.size(); + } + + + /** + * Get the name of an attribute (by position). + * + * @param i The position of the attribute in the list. + * @return The attribute name as a string, or null if there + * is no attribute at that position. + * @see org.xml.sax.AttributeList#getName(int) + */ + public String getName (int i) + { + if (i < 0) { + return null; + } + try { + return (String)names.elementAt(i); + } catch (ArrayIndexOutOfBoundsException e) { + return null; + } + } + + + /** + * Get the type of an attribute (by position). + * + * @param i The position of the attribute in the list. + * @return The attribute type as a string ("NMTOKEN" for an + * enumeration, and "CDATA" if no declaration was + * read), or null if there is no attribute at + * that position. + * @see org.xml.sax.AttributeList#getType(int) + */ + public String getType (int i) + { + if (i < 0) { + return null; + } + try { + return (String)types.elementAt(i); + } catch (ArrayIndexOutOfBoundsException e) { + return null; + } + } + + + /** + * Get the value of an attribute (by position). + * + * @param i The position of the attribute in the list. + * @return The attribute value as a string, or null if + * there is no attribute at that position. + * @see org.xml.sax.AttributeList#getValue(int) + */ + public String getValue (int i) + { + if (i < 0) { + return null; + } + try { + return (String)values.elementAt(i); + } catch (ArrayIndexOutOfBoundsException e) { + return null; + } + } + + + /** + * Get the type of an attribute (by name). + * + * @param name The attribute name. + * @return The attribute type as a string ("NMTOKEN" for an + * enumeration, and "CDATA" if no declaration was + * read). + * @see org.xml.sax.AttributeList#getType(java.lang.String) + */ + public String getType (String name) + { + return getType(names.indexOf(name)); + } + + + /** + * Get the value of an attribute (by name). + * + * @param name The attribute name. + * @return the named attribute's value or null, if the attribute does not + * exist. + * @see org.xml.sax.AttributeList#getValue(java.lang.String) + */ + public String getValue (String name) + { + return getValue(names.indexOf(name)); + } + + + + //////////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////////// + + Vector names = new Vector(); + Vector types = new Vector(); + Vector values = new Vector(); + +} + +// end of AttributeListImpl.java diff --git a/xml/src/main/java/org/xml/sax/helpers/AttributesImpl.java b/xml/src/main/java/org/xml/sax/helpers/AttributesImpl.java new file mode 100644 index 0000000..b740e23 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/AttributesImpl.java @@ -0,0 +1,618 @@ +// AttributesImpl.java - default implementation of Attributes. +// http://www.saxproject.org +// Written by David Megginson +// NO WARRANTY! This class is in the public domain. +// $Id: AttributesImpl.java,v 1.9 2002/01/30 20:52:24 dbrownell Exp $ + +package org.xml.sax.helpers; + +import org.xml.sax.Attributes; + + +/** + * Default implementation of the Attributes interface. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class provides a default implementation of the SAX2 + * {@link org.xml.sax.Attributes Attributes} interface, with the + * addition of manipulators so that the list can be modified or + * reused.</p> + * + * <p>There are two typical uses of this class:</p> + * + * <ol> + * <li>to take a persistent snapshot of an Attributes object + * in a {@link org.xml.sax.ContentHandler#startElement startElement} event; or</li> + * <li>to construct or modify an Attributes object in a SAX2 driver or filter.</li> + * </ol> + * + * <p>This class replaces the now-deprecated SAX1 {@link + * org.xml.sax.helpers.AttributeListImpl AttributeListImpl} + * class; in addition to supporting the updated Attributes + * interface rather than the deprecated {@link org.xml.sax.AttributeList + * AttributeList} interface, it also includes a much more efficient + * implementation using a single array rather than a set of Vectors.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + */ +public class AttributesImpl implements Attributes +{ + + + //////////////////////////////////////////////////////////////////// + // Constructors. + //////////////////////////////////////////////////////////////////// + + + /** + * Construct a new, empty AttributesImpl object. + */ + public AttributesImpl () + { + length = 0; + data = null; + } + + + /** + * Copy an existing Attributes object. + * + * <p>This constructor is especially useful inside a + * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p> + * + * @param atts The existing Attributes object. + */ + public AttributesImpl (Attributes atts) + { + setAttributes(atts); + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.Attributes. + //////////////////////////////////////////////////////////////////// + + + /** + * Return the number of attributes in the list. + * + * @return The number of attributes in the list. + * @see org.xml.sax.Attributes#getLength + */ + public int getLength () + { + return length; + } + + + /** + * Return an attribute's Namespace URI. + * + * @param index The attribute's index (zero-based). + * @return The Namespace URI, the empty string if none is + * available, or null if the index is out of range. + * @see org.xml.sax.Attributes#getURI + */ + public String getURI (int index) + { + if (index >= 0 && index < length) { + return data[index*5]; + } else { + return null; + } + } + + + /** + * Return an attribute's local name. + * + * @param index The attribute's index (zero-based). + * @return The attribute's local name, the empty string if + * none is available, or null if the index if out of range. + * @see org.xml.sax.Attributes#getLocalName + */ + public String getLocalName (int index) + { + if (index >= 0 && index < length) { + return data[index*5+1]; + } else { + return null; + } + } + + + /** + * Return an attribute's qualified (prefixed) name. + * + * @param index The attribute's index (zero-based). + * @return The attribute's qualified name, the empty string if + * none is available, or null if the index is out of bounds. + * @see org.xml.sax.Attributes#getQName + */ + public String getQName (int index) + { + if (index >= 0 && index < length) { + return data[index*5+2]; + } else { + return null; + } + } + + + /** + * Return an attribute's type by index. + * + * @param index The attribute's index (zero-based). + * @return The attribute's type, "CDATA" if the type is unknown, or null + * if the index is out of bounds. + * @see org.xml.sax.Attributes#getType(int) + */ + public String getType (int index) + { + if (index >= 0 && index < length) { + return data[index*5+3]; + } else { + return null; + } + } + + + /** + * Return an attribute's value by index. + * + * @param index The attribute's index (zero-based). + * @return The attribute's value or null if the index is out of bounds. + * @see org.xml.sax.Attributes#getValue(int) + */ + public String getValue (int index) + { + if (index >= 0 && index < length) { + return data[index*5+4]; + } else { + return null; + } + } + + + /** + * Look up an attribute's index by Namespace name. + * + * <p>In many cases, it will be more efficient to look up the name once and + * use the index query methods rather than using the name query methods + * repeatedly.</p> + * + * @param uri The attribute's Namespace URI, or the empty + * string if none is available. + * @param localName The attribute's local name. + * @return The attribute's index, or -1 if none matches. + * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String) + */ + public int getIndex (String uri, String localName) + { + int max = length * 5; + for (int i = 0; i < max; i += 5) { + if (data[i].equals(uri) && data[i+1].equals(localName)) { + return i / 5; + } + } + return -1; + } + + + /** + * Look up an attribute's index by qualified (prefixed) name. + * + * @param qName The qualified name. + * @return The attribute's index, or -1 if none matches. + * @see org.xml.sax.Attributes#getIndex(java.lang.String) + */ + public int getIndex (String qName) + { + int max = length * 5; + for (int i = 0; i < max; i += 5) { + if (data[i+2].equals(qName)) { + return i / 5; + } + } + return -1; + } + + + /** + * Look up an attribute's type by Namespace-qualified name. + * + * @param uri The Namespace URI, or the empty string for a name + * with no explicit Namespace URI. + * @param localName The local name. + * @return The attribute's type, or null if there is no + * matching attribute. + * @see org.xml.sax.Attributes#getType(java.lang.String,java.lang.String) + */ + public String getType (String uri, String localName) + { + int max = length * 5; + for (int i = 0; i < max; i += 5) { + if (data[i].equals(uri) && data[i+1].equals(localName)) { + return data[i+3]; + } + } + return null; + } + + + /** + * Look up an attribute's type by qualified (prefixed) name. + * + * @param qName The qualified name. + * @return The attribute's type, or null if there is no + * matching attribute. + * @see org.xml.sax.Attributes#getType(java.lang.String) + */ + public String getType (String qName) + { + int max = length * 5; + for (int i = 0; i < max; i += 5) { + if (data[i+2].equals(qName)) { + return data[i+3]; + } + } + return null; + } + + + /** + * Look up an attribute's value by Namespace-qualified name. + * + * @param uri The Namespace URI, or the empty string for a name + * with no explicit Namespace URI. + * @param localName The local name. + * @return The attribute's value, or null if there is no + * matching attribute. + * @see org.xml.sax.Attributes#getValue(java.lang.String,java.lang.String) + */ + public String getValue (String uri, String localName) + { + int max = length * 5; + for (int i = 0; i < max; i += 5) { + if (data[i].equals(uri) && data[i+1].equals(localName)) { + return data[i+4]; + } + } + return null; + } + + + /** + * Look up an attribute's value by qualified (prefixed) name. + * + * @param qName The qualified name. + * @return The attribute's value, or null if there is no + * matching attribute. + * @see org.xml.sax.Attributes#getValue(java.lang.String) + */ + public String getValue (String qName) + { + int max = length * 5; + for (int i = 0; i < max; i += 5) { + if (data[i+2].equals(qName)) { + return data[i+4]; + } + } + return null; + } + + + + //////////////////////////////////////////////////////////////////// + // Manipulators. + //////////////////////////////////////////////////////////////////// + + + /** + * Clear the attribute list for reuse. + * + * <p>Note that little memory is freed by this call: + * the current array is kept so it can be + * reused.</p> + */ + public void clear () + { + if (data != null) { + for (int i = 0; i < (length * 5); i++) + data [i] = null; + } + length = 0; + } + + + /** + * Copy an entire Attributes object. + * + * <p>It may be more efficient to reuse an existing object + * rather than constantly allocating new ones.</p> + * + * @param atts The attributes to copy. + */ + public void setAttributes (Attributes atts) + { + clear(); + length = atts.getLength(); + if (length > 0) { + data = new String[length*5]; + for (int i = 0; i < length; i++) { + data[i*5] = atts.getURI(i); + data[i*5+1] = atts.getLocalName(i); + data[i*5+2] = atts.getQName(i); + data[i*5+3] = atts.getType(i); + data[i*5+4] = atts.getValue(i); + } + } + } + + + /** + * Add an attribute to the end of the list. + * + * <p>For the sake of speed, this method does no checking + * to see if the attribute is already in the list: that is + * the responsibility of the application.</p> + * + * @param uri The Namespace URI, or the empty string if + * none is available or Namespace processing is not + * being performed. + * @param localName The local name, or the empty string if + * Namespace processing is not being performed. + * @param qName The qualified (prefixed) name, or the empty string + * if qualified names are not available. + * @param type The attribute type as a string. + * @param value The attribute value. + */ + public void addAttribute (String uri, String localName, String qName, + String type, String value) + { + ensureCapacity(length+1); + data[length*5] = uri; + data[length*5+1] = localName; + data[length*5+2] = qName; + data[length*5+3] = type; + data[length*5+4] = value; + length++; + } + + + /** + * Set an attribute in the list. + * + * <p>For the sake of speed, this method does no checking + * for name conflicts or well-formedness: such checks are the + * responsibility of the application.</p> + * + * @param index The index of the attribute (zero-based). + * @param uri The Namespace URI, or the empty string if + * none is available or Namespace processing is not + * being performed. + * @param localName The local name, or the empty string if + * Namespace processing is not being performed. + * @param qName The qualified name, or the empty string + * if qualified names are not available. + * @param type The attribute type as a string. + * @param value The attribute value. + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not point to an attribute + * in the list. + */ + public void setAttribute (int index, String uri, String localName, + String qName, String type, String value) + { + if (index >= 0 && index < length) { + data[index*5] = uri; + data[index*5+1] = localName; + data[index*5+2] = qName; + data[index*5+3] = type; + data[index*5+4] = value; + } else { + badIndex(index); + } + } + + + /** + * Remove an attribute from the list. + * + * @param index The index of the attribute (zero-based). + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not point to an attribute + * in the list. + */ + public void removeAttribute (int index) + { + if (index >= 0 && index < length) { + if (index < length - 1) { + System.arraycopy(data, (index+1)*5, data, index*5, + (length-index-1)*5); + } + index = (length - 1) * 5; + data [index++] = null; + data [index++] = null; + data [index++] = null; + data [index++] = null; + data [index] = null; + length--; + } else { + badIndex(index); + } + } + + + /** + * Set the Namespace URI of a specific attribute. + * + * @param index The index of the attribute (zero-based). + * @param uri The attribute's Namespace URI, or the empty + * string for none. + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not point to an attribute + * in the list. + */ + public void setURI (int index, String uri) + { + if (index >= 0 && index < length) { + data[index*5] = uri; + } else { + badIndex(index); + } + } + + + /** + * Set the local name of a specific attribute. + * + * @param index The index of the attribute (zero-based). + * @param localName The attribute's local name, or the empty + * string for none. + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not point to an attribute + * in the list. + */ + public void setLocalName (int index, String localName) + { + if (index >= 0 && index < length) { + data[index*5+1] = localName; + } else { + badIndex(index); + } + } + + + /** + * Set the qualified name of a specific attribute. + * + * @param index The index of the attribute (zero-based). + * @param qName The attribute's qualified name, or the empty + * string for none. + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not point to an attribute + * in the list. + */ + public void setQName (int index, String qName) + { + if (index >= 0 && index < length) { + data[index*5+2] = qName; + } else { + badIndex(index); + } + } + + + /** + * Set the type of a specific attribute. + * + * @param index The index of the attribute (zero-based). + * @param type The attribute's type. + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not point to an attribute + * in the list. + */ + public void setType (int index, String type) + { + if (index >= 0 && index < length) { + data[index*5+3] = type; + } else { + badIndex(index); + } + } + + + /** + * Set the value of a specific attribute. + * + * @param index The index of the attribute (zero-based). + * @param value The attribute's value. + * @exception java.lang.ArrayIndexOutOfBoundsException When the + * supplied index does not point to an attribute + * in the list. + */ + public void setValue (int index, String value) + { + if (index >= 0 && index < length) { + data[index*5+4] = value; + } else { + badIndex(index); + } + } + + + + //////////////////////////////////////////////////////////////////// + // Internal methods. + //////////////////////////////////////////////////////////////////// + + + /** + * Ensure the internal array's capacity. + * + * @param n The minimum number of attributes that the array must + * be able to hold. + */ + private void ensureCapacity (int n) { + if (n <= 0) { + return; + } + int max; + if (data == null || data.length == 0) { + max = 25; + } + else if (data.length >= n * 5) { + return; + } + else { + max = data.length; + } + while (max < n * 5) { + max *= 2; + } + + String newData[] = new String[max]; + if (length > 0) { + System.arraycopy(data, 0, newData, 0, length*5); + } + data = newData; + } + + + /** + * Report a bad array index in a manipulator. + * + * @param index The index to report. + * @exception java.lang.ArrayIndexOutOfBoundsException Always. + */ + private void badIndex (int index) + throws ArrayIndexOutOfBoundsException + { + String msg = + "Attempt to modify attribute at illegal index: " + index; + throw new ArrayIndexOutOfBoundsException(msg); + } + + + + //////////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////////// + + int length; + String data []; + +} + +// end of AttributesImpl.java + diff --git a/xml/src/main/java/org/xml/sax/helpers/DefaultHandler.java b/xml/src/main/java/org/xml/sax/helpers/DefaultHandler.java new file mode 100644 index 0000000..8308be7 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/DefaultHandler.java @@ -0,0 +1,467 @@ +// 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.9 2004/04/26 17:34:35 dmegginson Exp $ + +package org.xml.sax.helpers; + +import java.io.IOException; + +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; +import org.xml.sax.EntityResolver; +import org.xml.sax.DTDHandler; +import org.xml.sax.ContentHandler; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + + +/** + * Default base class for SAX2 event handlers. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class is available as a convenience base class for SAX2 + * applications: it provides default implementations for all of the + * callbacks in the four core SAX2 handler classes:</p> + * + * <ul> + * <li>{@link org.xml.sax.EntityResolver EntityResolver}</li> + * <li>{@link org.xml.sax.DTDHandler DTDHandler}</li> + * <li>{@link org.xml.sax.ContentHandler ContentHandler}</li> + * <li>{@link org.xml.sax.ErrorHandler ErrorHandler}</li> + * </ul> + * + * <p>Application writers can extend this class when they need to + * implement only part of an interface; parser writers can + * instantiate this class to provide default handlers when the + * application has not supplied its own.</p> + * + * <p>This class replaces the deprecated SAX1 + * {@link org.xml.sax.HandlerBase HandlerBase} class.</p> + * + * @since SAX 2.0 + * @author David Megginson, + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.EntityResolver + * @see org.xml.sax.DTDHandler + * @see org.xml.sax.ContentHandler + * @see org.xml.sax.ErrorHandler + */ +public class DefaultHandler + implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler +{ + + + //////////////////////////////////////////////////////////////////// + // Default implementation of the EntityResolver interface. + //////////////////////////////////////////////////////////////////// + + /** + * Resolve an external entity. + * + * <p>Always return null, so that the parser will use the system + * identifier provided in the XML document. This method implements + * the SAX default behaviour: application writers can override it + * in a subclass to do special translations such as catalog lookups + * or URI redirection.</p> + * + * @param publicId The public identifer, or null if none is + * available. + * @param systemId The system identifier provided in the XML + * document. + * @return The new input source, or null to require the + * default behaviour. + * @exception java.io.IOException If there is an error setting + * up the new input source. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.EntityResolver#resolveEntity + */ + public InputSource resolveEntity (String publicId, String systemId) + throws IOException, SAXException + { + return null; + } + + + + //////////////////////////////////////////////////////////////////// + // Default implementation of DTDHandler interface. + //////////////////////////////////////////////////////////////////// + + + /** + * Receive notification of a notation declaration. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass if they wish to keep track of the notations + * declared in a document.</p> + * + * @param name The notation name. + * @param publicId The notation public identifier, or null if not + * available. + * @param systemId The notation system identifier. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DTDHandler#notationDecl + */ + public void notationDecl (String name, String publicId, String systemId) + throws SAXException + { + // no op + } + + + /** + * Receive notification of an unparsed entity declaration. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to keep track of the unparsed entities + * declared in a document.</p> + * + * @param name The entity name. + * @param publicId The entity public identifier, or null if not + * available. + * @param systemId The entity system identifier. + * @param notationName The name of the associated notation. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.DTDHandler#unparsedEntityDecl + */ + public void unparsedEntityDecl (String name, String publicId, + String systemId, String notationName) + throws SAXException + { + // no op + } + + + + //////////////////////////////////////////////////////////////////// + // Default implementation of ContentHandler interface. + //////////////////////////////////////////////////////////////////// + + + /** + * Receive a Locator object for document events. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass if they wish to store the locator for use + * with other document events.</p> + * + * @param locator A locator for all SAX document events. + * @see org.xml.sax.ContentHandler#setDocumentLocator + * @see org.xml.sax.Locator + */ + public void setDocumentLocator (Locator locator) + { + // no op + } + + + /** + * Receive notification of the beginning of the document. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the beginning + * of a document (such as allocating the root node of a tree or + * creating an output file).</p> + * + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#startDocument + */ + public void startDocument () + throws SAXException + { + // no op + } + + + /** + * Receive notification of the end of the document. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end + * of a document (such as finalising a tree or closing an output + * file).</p> + * + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#endDocument + */ + public void endDocument () + throws SAXException + { + // no op + } + + + /** + * Receive notification of the start of a Namespace mapping. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the start of + * each Namespace prefix scope (such as storing the prefix mapping).</p> + * + * @param prefix The Namespace prefix being declared. + * @param uri The Namespace URI mapped to the prefix. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#startPrefixMapping + */ + public void startPrefixMapping (String prefix, String uri) + throws SAXException + { + // no op + } + + + /** + * Receive notification of the end of a Namespace mapping. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each prefix mapping.</p> + * + * @param prefix The Namespace prefix being declared. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#endPrefixMapping + */ + public void endPrefixMapping (String prefix) + throws SAXException + { + // no op + } + + + /** + * Receive notification of the start of an element. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the start of + * each element (such as allocating a new tree node or writing + * output to a file).</p> + * + * @param uri The Namespace URI, or the empty string if the + * element has no Namespace URI or if Namespace + * processing is not being performed. + * @param localName The local name (without prefix), or the + * empty string if Namespace processing is not being + * performed. + * @param qName The qualified name (with prefix), or the + * empty string if qualified names are not available. + * @param attributes The attributes attached to the element. If + * there are no attributes, it shall be an empty + * Attributes object. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#startElement + */ + public void startElement (String uri, String localName, + String qName, Attributes attributes) + throws SAXException + { + // no op + } + + + /** + * Receive notification of the end of an element. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions at the end of + * each element (such as finalising a tree node or writing + * output to a file).</p> + * + * @param uri The Namespace URI, or the empty string if the + * element has no Namespace URI or if Namespace + * processing is not being performed. + * @param localName The local name (without prefix), or the + * empty string if Namespace processing is not being + * performed. + * @param qName The qualified name (with prefix), or the + * empty string if qualified names are not available. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#endElement + */ + public void endElement (String uri, String localName, String qName) + throws SAXException + { + // no op + } + + + /** + * Receive notification of character data inside an element. + * + * <p>By default, do nothing. Application writers may override this + * method to take specific actions for each chunk of character data + * (such as adding the data to a node or buffer, or printing it to + * a file).</p> + * + * @param ch The characters. + * @param start The start position in the character array. + * @param length The number of characters to use from the + * character array. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#characters + */ + public void characters (char ch[], int start, int length) + throws SAXException + { + // no op + } + + + /** + * Receive notification of ignorable whitespace in element content. + * + * <p>By default, do nothing. Application writers may override this + * method to take specific actions for each chunk of ignorable + * whitespace (such as adding data to a node or buffer, or printing + * it to a file).</p> + * + * @param ch The whitespace characters. + * @param start The start position in the character array. + * @param length The number of characters to use from the + * character array. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#ignorableWhitespace + */ + public void ignorableWhitespace (char ch[], int start, int length) + throws SAXException + { + // no op + } + + + /** + * Receive notification of a processing instruction. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions for each + * processing instruction, such as setting status variables or + * invoking other methods.</p> + * + * @param target The processing instruction target. + * @param data The processing instruction data, or null if + * none is supplied. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#processingInstruction + */ + public void processingInstruction (String target, String data) + throws SAXException + { + // no op + } + + + /** + * Receive notification of a skipped entity. + * + * <p>By default, do nothing. Application writers may override this + * method in a subclass to take specific actions for each + * processing instruction, such as setting status variables or + * invoking other methods.</p> + * + * @param name The name of the skipped entity. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ContentHandler#processingInstruction + */ + public void skippedEntity (String name) + throws SAXException + { + // no op + } + + + + //////////////////////////////////////////////////////////////////// + // Default implementation of the ErrorHandler interface. + //////////////////////////////////////////////////////////////////// + + + /** + * Receive notification of a parser warning. + * + * <p>The default implementation does nothing. Application writers + * may override this method in a subclass to take specific actions + * for each warning, such as inserting the message in a log file or + * printing it to the console.</p> + * + * @param e The warning information encoded as an exception. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ErrorHandler#warning + * @see org.xml.sax.SAXParseException + */ + public void warning (SAXParseException e) + throws SAXException + { + // no op + } + + + /** + * Receive notification of a recoverable parser error. + * + * <p>The default implementation does nothing. Application writers + * may override this method in a subclass to take specific actions + * for each error, such as inserting the message in a log file or + * printing it to the console.</p> + * + * @param e The 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 error (SAXParseException e) + throws SAXException + { + // no op + } + + + /** + * Report a fatal XML parsing error. + * + * <p>The default implementation throws a SAXParseException. + * Application writers may override this method in a subclass if + * they need to take specific actions for each fatal error (such as + * collecting all of the errors into a single report): in any case, + * the application must stop all regular processing when this + * method is invoked, since the document is no longer reliable, and + * the parser may no longer report parsing events.</p> + * + * @param e The error information encoded as an exception. + * @exception org.xml.sax.SAXException Any SAX exception, possibly + * wrapping another exception. + * @see org.xml.sax.ErrorHandler#fatalError + * @see org.xml.sax.SAXParseException + */ + public void fatalError (SAXParseException e) + throws SAXException + { + throw e; + } + +} + +// end of DefaultHandler.java diff --git a/xml/src/main/java/org/xml/sax/helpers/LocatorImpl.java b/xml/src/main/java/org/xml/sax/helpers/LocatorImpl.java new file mode 100644 index 0000000..18445bc --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/LocatorImpl.java @@ -0,0 +1,214 @@ +// SAX default implementation for Locator. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: LocatorImpl.java,v 1.6 2002/01/30 20:52:27 dbrownell Exp $ + +package org.xml.sax.helpers; + +import org.xml.sax.Locator; + + +/** + * Provide an optional convenience implementation of Locator. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class is available mainly for application writers, who + * can use it to make a persistent snapshot of a locator at any + * point during a document parse:</p> + * + * <pre> + * Locator locator; + * Locator startloc; + * + * public void setLocator (Locator locator) + * { + * // note the locator + * this.locator = locator; + * } + * + * public void startDocument () + * { + * // save the location of the start of the document + * // for future use. + * Locator startloc = new LocatorImpl(locator); + * } + *</pre> + * + * <p>Normally, parser writers will not use this class, since it + * is more efficient to provide location information only when + * requested, rather than constantly updating a Locator object.</p> + * + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.Locator Locator + */ +public class LocatorImpl implements Locator +{ + + + /** + * Zero-argument constructor. + * + * <p>This will not normally be useful, since the main purpose + * of this class is to make a snapshot of an existing Locator.</p> + */ + public LocatorImpl () + { + } + + + /** + * Copy constructor. + * + * <p>Create a persistent copy of the current state of a locator. + * When the original locator changes, this copy will still keep + * the original values (and it can be used outside the scope of + * DocumentHandler methods).</p> + * + * @param locator The locator to copy. + */ + public LocatorImpl (Locator locator) + { + setPublicId(locator.getPublicId()); + setSystemId(locator.getSystemId()); + setLineNumber(locator.getLineNumber()); + setColumnNumber(locator.getColumnNumber()); + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.Locator + //////////////////////////////////////////////////////////////////// + + + /** + * Return the saved public identifier. + * + * @return The public identifier as a string, or null if none + * is available. + * @see org.xml.sax.Locator#getPublicId + * @see #setPublicId + */ + public String getPublicId () + { + return publicId; + } + + + /** + * Return the saved system identifier. + * + * @return The system identifier as a string, or null if none + * is available. + * @see org.xml.sax.Locator#getSystemId + * @see #setSystemId + */ + public String getSystemId () + { + return systemId; + } + + + /** + * Return the saved line number (1-based). + * + * @return The line number as an integer, or -1 if none is available. + * @see org.xml.sax.Locator#getLineNumber + * @see #setLineNumber + */ + public int getLineNumber () + { + return lineNumber; + } + + + /** + * Return the saved column number (1-based). + * + * @return The column number as an integer, or -1 if none is available. + * @see org.xml.sax.Locator#getColumnNumber + * @see #setColumnNumber + */ + public int getColumnNumber () + { + return columnNumber; + } + + + + //////////////////////////////////////////////////////////////////// + // Setters for the properties (not in org.xml.sax.Locator) + //////////////////////////////////////////////////////////////////// + + + /** + * Set the public identifier for this locator. + * + * @param publicId The new public identifier, or null + * if none is available. + * @see #getPublicId + */ + public void setPublicId (String publicId) + { + this.publicId = publicId; + } + + + /** + * Set the system identifier for this locator. + * + * @param systemId The new system identifier, or null + * if none is available. + * @see #getSystemId + */ + public void setSystemId (String systemId) + { + this.systemId = systemId; + } + + + /** + * Set the line number for this locator (1-based). + * + * @param lineNumber The line number, or -1 if none is available. + * @see #getLineNumber + */ + public void setLineNumber (int lineNumber) + { + this.lineNumber = lineNumber; + } + + + /** + * Set the column number for this locator (1-based). + * + * @param columnNumber The column number, or -1 if none is available. + * @see #getColumnNumber + */ + public void setColumnNumber (int columnNumber) + { + this.columnNumber = columnNumber; + } + + + + //////////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////////// + + private String publicId; + private String systemId; + private int lineNumber; + private int columnNumber; + +} + +// end of LocatorImpl.java diff --git a/xml/src/main/java/org/xml/sax/helpers/NamespaceSupport.java b/xml/src/main/java/org/xml/sax/helpers/NamespaceSupport.java new file mode 100644 index 0000000..a737d1d --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/NamespaceSupport.java @@ -0,0 +1,840 @@ +// NamespaceSupport.java - generic Namespace support for SAX. +// http://www.saxproject.org +// Written by David Megginson +// This class is in the Public Domain. NO WARRANTY! +// $Id: NamespaceSupport.java,v 1.15 2004/04/26 17:34:35 dmegginson Exp $ + +package org.xml.sax.helpers; + +import java.util.EmptyStackException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + + +/** + * Encapsulate Namespace logic for use by applications using SAX, + * or internally by SAX drivers. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class encapsulates the logic of Namespace processing: it + * tracks the declarations currently in force for each context and + * automatically processes qualified XML names into their Namespace + * parts; it can also be used in reverse for generating XML qnames + * from Namespaces.</p> + * + * <p>Namespace support objects are reusable, but the reset method + * must be invoked between each session.</p> + * + * <p>Here is a simple session:</p> + * + * <pre> + * String parts[] = new String[3]; + * NamespaceSupport support = new NamespaceSupport(); + * + * support.pushContext(); + * support.declarePrefix("", "http://www.w3.org/1999/xhtml"); + * support.declarePrefix("dc", "http://www.purl.org/dc#"); + * + * parts = support.processName("p", parts, false); + * System.out.println("Namespace URI: " + parts[0]); + * System.out.println("Local name: " + parts[1]); + * System.out.println("Raw name: " + parts[2]); + * + * parts = support.processName("dc:title", parts, false); + * System.out.println("Namespace URI: " + parts[0]); + * System.out.println("Local name: " + parts[1]); + * System.out.println("Raw name: " + parts[2]); + * + * support.popContext(); + * </pre> + * + * <p>Note that this class is optimized for the use case where most + * elements do not contain Namespace declarations: if the same + * prefix/URI mapping is repeated for each context (for example), this + * class will be somewhat less efficient.</p> + * + * <p>Although SAX drivers (parsers) may choose to use this class to + * implement namespace handling, they are not required to do so. + * Applications must track namespace information themselves if they + * want to use namespace information. + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + */ +public class NamespaceSupport +{ + + + //////////////////////////////////////////////////////////////////// + // Constants. + //////////////////////////////////////////////////////////////////// + + + /** + * The XML Namespace URI as a constant. + * The value is <code>http://www.w3.org/XML/1998/namespace</code> + * as defined in the "Namespaces in XML" * recommendation. + * + * <p>This is the Namespace URI that is automatically mapped + * to the "xml" prefix.</p> + */ + public final static String XMLNS = + "http://www.w3.org/XML/1998/namespace"; + + + /** + * The namespace declaration URI as a constant. + * The value is <code>http://www.w3.org/xmlns/2000/</code>, as defined + * in a backwards-incompatible erratum to the "Namespaces in XML" + * recommendation. Because that erratum postdated SAX2, SAX2 defaults + * to the original recommendation, and does not normally use this URI. + * + * + * <p>This is the Namespace URI that is optionally applied to + * <em>xmlns</em> and <em>xmlns:*</em> attributes, which are used to + * declare namespaces. </p> + * + * @since SAX 2.1alpha + * @see #setNamespaceDeclUris + * @see #isNamespaceDeclUris + */ + public final static String NSDECL = + "http://www.w3.org/xmlns/2000/"; + + + /** + * An empty enumeration. + */ + private final static Enumeration EMPTY_ENUMERATION = + new Vector().elements(); + + + //////////////////////////////////////////////////////////////////// + // Constructor. + //////////////////////////////////////////////////////////////////// + + + /** + * Create a new Namespace support object. + */ + public NamespaceSupport () + { + reset(); + } + + + + //////////////////////////////////////////////////////////////////// + // Context management. + //////////////////////////////////////////////////////////////////// + + + /** + * Reset this Namespace support object for reuse. + * + * <p>It is necessary to invoke this method before reusing the + * Namespace support object for a new session. If namespace + * declaration URIs are to be supported, that flag must also + * be set to a non-default value. + * </p> + * + * @see #setNamespaceDeclUris + */ + public void reset () + { + contexts = new Context[32]; + namespaceDeclUris = false; + contextPos = 0; + contexts[contextPos] = currentContext = new Context(); + currentContext.declarePrefix("xml", XMLNS); + } + + + /** + * Start a new Namespace context. + * The new context will automatically inherit + * the declarations of its parent context, but it will also keep + * track of which declarations were made within this context. + * + * <p>Event callback code should start a new context once per element. + * This means being ready to call this in either of two places. + * For elements that don't include namespace declarations, the + * <em>ContentHandler.startElement()</em> callback is the right place. + * For elements with such a declaration, it'd done in the first + * <em>ContentHandler.startPrefixMapping()</em> callback. + * A boolean flag can be used to + * track whether a context has been started yet. When either of + * those methods is called, it checks the flag to see if a new context + * needs to be started. If so, it starts the context and sets the + * flag. After <em>ContentHandler.startElement()</em> + * does that, it always clears the flag. + * + * <p>Normally, SAX drivers would push a new context at the beginning + * of each XML element. Then they perform a first pass over the + * attributes to process all namespace declarations, making + * <em>ContentHandler.startPrefixMapping()</em> callbacks. + * Then a second pass is made, to determine the namespace-qualified + * names for all attributes and for the element name. + * Finally all the information for the + * <em>ContentHandler.startElement()</em> callback is available, + * so it can then be made. + * + * <p>The Namespace support object always starts with a base context + * already in force: in this context, only the "xml" prefix is + * declared.</p> + * + * @see org.xml.sax.ContentHandler + * @see #popContext + */ + public void pushContext () + { + int max = contexts.length; + + contexts [contextPos].declsOK = false; + contextPos++; + + // Extend the array if necessary + if (contextPos >= max) { + Context newContexts[] = new Context[max*2]; + System.arraycopy(contexts, 0, newContexts, 0, max); + max *= 2; + contexts = newContexts; + } + + // Allocate the context if necessary. + currentContext = contexts[contextPos]; + if (currentContext == null) { + contexts[contextPos] = currentContext = new Context(); + } + + // Set the parent, if any. + if (contextPos > 0) { + currentContext.setParent(contexts[contextPos - 1]); + } + } + + + /** + * Revert to the previous Namespace context. + * + * <p>Normally, you should pop the context at the end of each + * XML element. After popping the context, all Namespace prefix + * mappings that were previously in force are restored.</p> + * + * <p>You must not attempt to declare additional Namespace + * prefixes after popping a context, unless you push another + * context first.</p> + * + * @see #pushContext + */ + public void popContext () + { + contexts[contextPos].clear(); + contextPos--; + if (contextPos < 0) { + throw new EmptyStackException(); + } + currentContext = contexts[contextPos]; + } + + + + //////////////////////////////////////////////////////////////////// + // Operations within a context. + //////////////////////////////////////////////////////////////////// + + + /** + * Declare a Namespace prefix. All prefixes must be declared + * before they are referenced. For example, a SAX driver (parser) + * would scan an element's attributes + * in two passes: first for namespace declarations, + * then a second pass using {@link #processName processName()} to + * interpret prefixes against (potentially redefined) prefixes. + * + * <p>This method declares a prefix in the current Namespace + * context; the prefix will remain in force until this context + * is popped, unless it is shadowed in a descendant context.</p> + * + * <p>To declare the default element Namespace, use the empty string as + * the prefix.</p> + * + * <p>Note that you must <em>not</em> declare a prefix after + * you've pushed and popped another Namespace context, or + * treated the declarations phase as complete by processing + * a prefixed name.</p> + * + * <p>Note that there is an asymmetry in this library: {@link + * #getPrefix getPrefix} will not return the "" prefix, + * even if you have declared a default element namespace. + * To check for a default namespace, + * you have to look it up explicitly using {@link #getURI getURI}. + * This asymmetry exists to make it easier to look up prefixes + * for attribute names, where the default prefix is not allowed.</p> + * + * @param prefix The prefix to declare, or the empty string to + * indicate the default element namespace. This may never have + * the value "xml" or "xmlns". + * @param uri The Namespace URI to associate with the prefix. + * @return true if the prefix was legal, false otherwise + * + * @see #processName + * @see #getURI + * @see #getPrefix + */ + public boolean declarePrefix (String prefix, String uri) + { + if (prefix.equals("xml") || prefix.equals("xmlns")) { + return false; + } else { + currentContext.declarePrefix(prefix, uri); + return true; + } + } + + + /** + * Process a raw XML qualified name, after all declarations in the + * current context have been handled by {@link #declarePrefix + * declarePrefix()}. + * + * <p>This method processes a raw XML qualified name in the + * current context by removing the prefix and looking it up among + * the prefixes currently declared. The return value will be the + * array supplied by the caller, filled in as follows:</p> + * + * <dl> + * <dt>parts[0]</dt> + * <dd>The Namespace URI, or an empty string if none is + * in use.</dd> + * <dt>parts[1]</dt> + * <dd>The local name (without prefix).</dd> + * <dt>parts[2]</dt> + * <dd>The original raw name.</dd> + * </dl> + * + * <p>All of the strings in the array will be internalized. If + * the raw name has a prefix that has not been declared, then + * the return value will be null.</p> + * + * <p>Note that attribute names are processed differently than + * element names: an unprefixed element name will receive the + * default Namespace (if any), while an unprefixed attribute name + * will not.</p> + * + * @param qName The XML qualified name to be processed. + * @param parts An array supplied by the caller, capable of + * holding at least three members. + * @param isAttribute A flag indicating whether this is an + * attribute name (true) or an element name (false). + * @return The supplied array holding three internalized strings + * representing the Namespace URI (or empty string), the + * local name, and the XML qualified name; or null if there + * is an undeclared prefix. + * @see #declarePrefix + * @see java.lang.String#intern */ + public String [] processName (String qName, String parts[], + boolean isAttribute) + { + String myParts[] = currentContext.processName(qName, isAttribute); + if (myParts == null) { + return null; + } else { + parts[0] = myParts[0]; + parts[1] = myParts[1]; + parts[2] = myParts[2]; + return parts; + } + } + + + /** + * Look up a prefix and get the currently-mapped Namespace URI. + * + * <p>This method looks up the prefix in the current context. + * Use the empty string ("") for the default Namespace.</p> + * + * @param prefix The prefix to look up. + * @return The associated Namespace URI, or null if the prefix + * is undeclared in this context. + * @see #getPrefix + * @see #getPrefixes + */ + public String getURI (String prefix) + { + return currentContext.getURI(prefix); + } + + + /** + * Return an enumeration of all prefixes whose declarations are + * active in the current context. + * This includes declarations from parent contexts that have + * not been overridden. + * + * <p><strong>Note:</strong> if there is a default prefix, it will not be + * returned in this enumeration; check for the default prefix + * using the {@link #getURI getURI} with an argument of "".</p> + * + * @return An enumeration of prefixes (never empty). + * @see #getDeclaredPrefixes + * @see #getURI + */ + public Enumeration getPrefixes () + { + return currentContext.getPrefixes(); + } + + + /** + * Return one of the prefixes mapped to a Namespace URI. + * + * <p>If more than one prefix is currently mapped to the same + * URI, this method will make an arbitrary selection; if you + * want all of the prefixes, use the {@link #getPrefixes} + * method instead.</p> + * + * <p><strong>Note:</strong> this will never return the empty (default) prefix; + * to check for a default prefix, use the {@link #getURI getURI} + * method with an argument of "".</p> + * + * @param uri the namespace URI + * @return one of the prefixes currently mapped to the URI supplied, + * or null if none is mapped or if the URI is assigned to + * the default namespace + * @see #getPrefixes(java.lang.String) + * @see #getURI + */ + public String getPrefix (String uri) + { + return currentContext.getPrefix(uri); + } + + + /** + * Return an enumeration of all prefixes for a given URI whose + * declarations are active in the current context. + * This includes declarations from parent contexts that have + * not been overridden. + * + * <p>This method returns prefixes mapped to a specific Namespace + * URI. The xml: prefix will be included. If you want only one + * prefix that's mapped to the Namespace URI, and you don't care + * which one you get, use the {@link #getPrefix getPrefix} + * method instead.</p> + * + * <p><strong>Note:</strong> the empty (default) prefix is <em>never</em> included + * in this enumeration; to check for the presence of a default + * Namespace, use the {@link #getURI getURI} method with an + * argument of "".</p> + * + * @param uri The Namespace URI. + * @return An enumeration of prefixes (never empty). + * @see #getPrefix + * @see #getDeclaredPrefixes + * @see #getURI + */ + public Enumeration getPrefixes (String uri) + { + Vector prefixes = new Vector(); + Enumeration allPrefixes = getPrefixes(); + while (allPrefixes.hasMoreElements()) { + String prefix = (String)allPrefixes.nextElement(); + if (uri.equals(getURI(prefix))) { + prefixes.addElement(prefix); + } + } + return prefixes.elements(); + } + + + /** + * Return an enumeration of all prefixes declared in this context. + * + * <p>The empty (default) prefix will be included in this + * enumeration; note that this behaviour differs from that of + * {@link #getPrefix} and {@link #getPrefixes}.</p> + * + * @return An enumeration of all prefixes declared in this + * context. + * @see #getPrefixes + * @see #getURI + */ + public Enumeration getDeclaredPrefixes () + { + return currentContext.getDeclaredPrefixes(); + } + + /** + * Controls whether namespace declaration attributes are placed + * into the {@link #NSDECL NSDECL} namespace + * by {@link #processName processName()}. This may only be + * changed before any contexts have been pushed. + * + * @param value the namespace declaration attribute state. A value of true + * enables this feature, a value of false disables it. + * + * @since SAX 2.1alpha + * + * @exception IllegalStateException when attempting to set this + * after any context has been pushed. + */ + public void setNamespaceDeclUris (boolean value) + { + if (contextPos != 0) + throw new IllegalStateException (); + if (value == namespaceDeclUris) + return; + namespaceDeclUris = value; + if (value) + currentContext.declarePrefix ("xmlns", NSDECL); + else { + contexts[contextPos] = currentContext = new Context(); + currentContext.declarePrefix("xml", XMLNS); + } + } + + /** + * Returns true if namespace declaration attributes are placed into + * a namespace. This behavior is not the default. + * + * @return true if namespace declaration attributes are enabled, false + * otherwise. + * @since SAX 2.1alpha + */ + public boolean isNamespaceDeclUris () + { return namespaceDeclUris; } + + + + //////////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////////// + + private Context contexts[]; + private Context currentContext; + private int contextPos; + private boolean namespaceDeclUris; + + + //////////////////////////////////////////////////////////////////// + // Internal classes. + //////////////////////////////////////////////////////////////////// + + /** + * Internal class for a single Namespace context. + * + * <p>This module caches and reuses Namespace contexts, + * so the number allocated + * will be equal to the element depth of the document, not to the total + * number of elements (i.e. 5-10 rather than tens of thousands). + * Also, data structures used to represent contexts are shared when + * possible (child contexts without declarations) to further reduce + * the amount of memory that's consumed. + * </p> + */ + final class Context { + + /** + * Create the root-level Namespace context. + */ + Context () + { + copyTables(); + } + + + /** + * (Re)set the parent of this Namespace context. + * The context must either have been freshly constructed, + * or must have been cleared. + * + * @param context The parent Namespace context object. + */ + void setParent (Context parent) + { + this.parent = parent; + declarations = null; + prefixTable = parent.prefixTable; + uriTable = parent.uriTable; + elementNameTable = parent.elementNameTable; + attributeNameTable = parent.attributeNameTable; + defaultNS = parent.defaultNS; + declSeen = false; + declsOK = true; + } + + /** + * Makes associated state become collectible, + * invalidating this context. + * {@link #setParent} must be called before + * this context may be used again. + */ + void clear () + { + parent = null; + prefixTable = null; + uriTable = null; + elementNameTable = null; + attributeNameTable = null; + defaultNS = null; + } + + + /** + * Declare a Namespace prefix for this context. + * + * @param prefix The prefix to declare. + * @param uri The associated Namespace URI. + * @see org.xml.sax.helpers.NamespaceSupport#declarePrefix + */ + void declarePrefix (String prefix, String uri) + { + // Lazy processing... + if (!declsOK) + throw new IllegalStateException ( + "can't declare any more prefixes in this context"); + if (!declSeen) { + copyTables(); + } + if (declarations == null) { + declarations = new Vector(); + } + + prefix = prefix.intern(); + uri = uri.intern(); + if ("".equals(prefix)) { + if ("".equals(uri)) { + defaultNS = null; + } else { + defaultNS = uri; + } + } else { + prefixTable.put(prefix, uri); + uriTable.put(uri, prefix); // may wipe out another prefix + } + declarations.addElement(prefix); + } + + + /** + * Process an XML qualified name in this context. + * + * @param qName The XML qualified name. + * @param isAttribute true if this is an attribute name. + * @return An array of three strings containing the + * URI part (or empty string), the local part, + * and the raw name, all internalized, or null + * if there is an undeclared prefix. + * @see org.xml.sax.helpers.NamespaceSupport#processName + */ + String [] processName (String qName, boolean isAttribute) + { + String name[]; + Hashtable table; + + // detect errors in call sequence + declsOK = false; + + // Select the appropriate table. + if (isAttribute) { + table = attributeNameTable; + } else { + table = elementNameTable; + } + + // Start by looking in the cache, and + // return immediately if the name + // is already known in this content + name = (String[])table.get(qName); + if (name != null) { + return name; + } + + // We haven't seen this name in this + // context before. Maybe in the parent + // context, but we can't assume prefix + // bindings are the same. + name = new String[3]; + name[2] = qName.intern(); + int index = qName.indexOf(':'); + + + // No prefix. + if (index == -1) { + if (isAttribute) { + if (qName == "xmlns" && namespaceDeclUris) + name[0] = NSDECL; + else + name[0] = ""; + } else if (defaultNS == null) { + name[0] = ""; + } else { + name[0] = defaultNS; + } + name[1] = name[2]; + } + + // Prefix + else { + String prefix = qName.substring(0, index); + String local = qName.substring(index+1); + String uri; + if ("".equals(prefix)) { + uri = defaultNS; + } else { + uri = (String)prefixTable.get(prefix); + } + if (uri == null + || (!isAttribute && "xmlns".equals (prefix))) { + return null; + } + name[0] = uri; + name[1] = local.intern(); + } + + // Save in the cache for future use. + // (Could be shared with parent context...) + table.put(name[2], name); + return name; + } + + + /** + * Look up the URI associated with a prefix in this context. + * + * @param prefix The prefix to look up. + * @return The associated Namespace URI, or null if none is + * declared. + * @see org.xml.sax.helpers.NamespaceSupport#getURI + */ + String getURI (String prefix) + { + if ("".equals(prefix)) { + return defaultNS; + } else if (prefixTable == null) { + return null; + } else { + return (String)prefixTable.get(prefix); + } + } + + + /** + * Look up one of the prefixes associated with a URI in this context. + * + * <p>Since many prefixes may be mapped to the same URI, + * the return value may be unreliable.</p> + * + * @param uri The URI to look up. + * @return The associated prefix, or null if none is declared. + * @see org.xml.sax.helpers.NamespaceSupport#getPrefix + */ + String getPrefix (String uri) + { + if (uriTable == null) { + return null; + } else { + return (String)uriTable.get(uri); + } + } + + + /** + * Return an enumeration of prefixes declared in this context. + * + * @return An enumeration of prefixes (possibly empty). + * @see org.xml.sax.helpers.NamespaceSupport#getDeclaredPrefixes + */ + Enumeration getDeclaredPrefixes () + { + if (declarations == null) { + return EMPTY_ENUMERATION; + } else { + return declarations.elements(); + } + } + + + /** + * Return an enumeration of all prefixes currently in force. + * + * <p>The default prefix, if in force, is <em>not</em> + * returned, and will have to be checked for separately.</p> + * + * @return An enumeration of prefixes (never empty). + * @see org.xml.sax.helpers.NamespaceSupport#getPrefixes + */ + Enumeration getPrefixes () + { + if (prefixTable == null) { + return EMPTY_ENUMERATION; + } else { + return prefixTable.keys(); + } + } + + + + //////////////////////////////////////////////////////////////// + // Internal methods. + //////////////////////////////////////////////////////////////// + + + /** + * Copy on write for the internal tables in this context. + * + * <p>This class is optimized for the normal case where most + * elements do not contain Namespace declarations.</p> + */ + private void copyTables () + { + if (prefixTable != null) { + prefixTable = (Hashtable)prefixTable.clone(); + } else { + prefixTable = new Hashtable(); + } + if (uriTable != null) { + uriTable = (Hashtable)uriTable.clone(); + } else { + uriTable = new Hashtable(); + } + elementNameTable = new Hashtable(); + attributeNameTable = new Hashtable(); + declSeen = true; + } + + + + //////////////////////////////////////////////////////////////// + // Protected state. + //////////////////////////////////////////////////////////////// + + Hashtable prefixTable; + Hashtable uriTable; + Hashtable elementNameTable; + Hashtable attributeNameTable; + String defaultNS = null; + boolean declsOK = true; + + + + //////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////// + + private Vector declarations = null; + private boolean declSeen = false; + private Context parent = null; + } +} + +// end of NamespaceSupport.java diff --git a/xml/src/main/java/org/xml/sax/helpers/NewInstance.java b/xml/src/main/java/org/xml/sax/helpers/NewInstance.java new file mode 100644 index 0000000..e590192 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/NewInstance.java @@ -0,0 +1,79 @@ +// NewInstance.java - create a new instance of a class by name. +// http://www.saxproject.org +// Written by Edwin Goei, edwingo@apache.org +// and by David Brownell, dbrownell@users.sourceforge.net +// NO WARRANTY! This class is in the Public Domain. +// $Id: NewInstance.java,v 1.4 2002/01/30 20:52:27 dbrownell Exp $ + +package org.xml.sax.helpers; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +/** + * Create a new instance of a class by name. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class contains a static method for creating an instance of a + * class from an explicit class name. It tries to use the thread's context + * ClassLoader if possible and falls back to using + * Class.forName(String).</p> + * + * <p>This code is designed to compile and run on JDK version 1.1 and later + * including versions of Java 2.</p> + * + * @author Edwin Goei, David Brownell + * @version 2.0.1 (sax2r2) + */ +class NewInstance { + + /** + * Creates a new instance of the specified class name + * + * Package private so this code is not exposed at the API level. + */ + static Object newInstance (ClassLoader classLoader, String className) + throws ClassNotFoundException, IllegalAccessException, + InstantiationException + { + Class driverClass; + if (classLoader == null) { + driverClass = Class.forName(className); + } else { + driverClass = classLoader.loadClass(className); + } + return driverClass.newInstance(); + } + + /** + * Figure out which ClassLoader to use. For JDK 1.2 and later use + * the context ClassLoader. + */ + static ClassLoader getClassLoader () + { + Method m = null; + + try { + m = Thread.class.getMethod("getContextClassLoader"); + } catch (NoSuchMethodException e) { + // Assume that we are running JDK 1.1, use the current ClassLoader + return NewInstance.class.getClassLoader(); + } + + try { + return (ClassLoader) m.invoke(Thread.currentThread()); + } catch (IllegalAccessException e) { + // assert(false) + throw new UnknownError(e.getMessage()); + } catch (InvocationTargetException e) { + // assert(e.getTargetException() instanceof SecurityException) + throw new UnknownError(e.getMessage()); + } + } +} diff --git a/xml/src/main/java/org/xml/sax/helpers/ParserAdapter.java b/xml/src/main/java/org/xml/sax/helpers/ParserAdapter.java new file mode 100644 index 0000000..7fc3813 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/ParserAdapter.java @@ -0,0 +1,1046 @@ +// ParserAdapter.java - adapt a SAX1 Parser to a SAX2 XMLReader. +// http://www.saxproject.org +// Written by David Megginson +// NO WARRANTY! This class is in the public domain. +// $Id: ParserAdapter.java,v 1.16 2004/04/26 17:34:35 dmegginson Exp $ + +package org.xml.sax.helpers; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; + +import org.xml.sax.Parser; // deprecated +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.AttributeList; // deprecated +import org.xml.sax.EntityResolver; +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; // deprecated +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import org.xml.sax.XMLReader; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; + + +/** + * Adapt a SAX1 Parser as a SAX2 XMLReader. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class wraps a SAX1 {@link org.xml.sax.Parser Parser} + * and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader}, + * with feature, property, and Namespace support. Note + * that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity + * skippedEntity} events, since SAX1 does not make that information available.</p> + * + * <p>This adapter does not test for duplicate Namespace-qualified + * attribute names.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.helpers.XMLReaderAdapter + * @see org.xml.sax.XMLReader + * @see org.xml.sax.Parser + */ +public class ParserAdapter implements XMLReader, DocumentHandler +{ + + + //////////////////////////////////////////////////////////////////// + // Constructors. + //////////////////////////////////////////////////////////////////// + + + /** + * Construct a new parser adapter. + * + * <p>Use the "org.xml.sax.parser" property to locate the + * embedded SAX1 driver.</p> + * + * @exception SAXException If the embedded driver + * cannot be instantiated or if the + * org.xml.sax.parser property is not specified. + */ + public ParserAdapter () + throws SAXException + { + super(); + + String driver = System.getProperty("org.xml.sax.parser"); + + try { + setup(ParserFactory.makeParser()); + } catch (ClassNotFoundException e1) { + throw new + SAXException("Cannot find SAX1 driver class " + + driver, e1); + } catch (IllegalAccessException e2) { + throw new + SAXException("SAX1 driver class " + + driver + + " found but cannot be loaded", e2); + } catch (InstantiationException e3) { + throw new + SAXException("SAX1 driver class " + + driver + + " loaded but cannot be instantiated", e3); + } catch (ClassCastException e4) { + throw new + SAXException("SAX1 driver class " + + driver + + " does not implement org.xml.sax.Parser"); + } catch (NullPointerException e5) { + throw new + SAXException("System property org.xml.sax.parser not specified"); + } + } + + + /** + * Construct a new parser adapter. + * + * <p>Note that the embedded parser cannot be changed once the + * adapter is created; to embed a different parser, allocate + * a new ParserAdapter.</p> + * + * @param parser The SAX1 parser to embed. + * @exception java.lang.NullPointerException If the parser parameter + * is null. + */ + public ParserAdapter (Parser parser) + { + super(); + setup(parser); + } + + + /** + * Internal setup method. + * + * @param parser The embedded parser. + * @exception java.lang.NullPointerException If the parser parameter + * is null. + */ + private void setup (Parser parser) + { + if (parser == null) { + throw new + NullPointerException("Parser argument must not be null"); + } + this.parser = parser; + atts = new AttributesImpl(); + nsSupport = new NamespaceSupport(); + attAdapter = new AttributeListAdapter(); + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.XMLReader. + //////////////////////////////////////////////////////////////////// + + + // + // Internal constants for the sake of convenience. + // + private final static String FEATURES = "http://xml.org/sax/features/"; + private final static String NAMESPACES = FEATURES + "namespaces"; + private final static String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes"; + private final static String XMLNS_URIs = FEATURES + "xmlns-uris"; + + + /** + * Set a feature flag for the parser. + * + * <p>The only features recognized are namespaces and + * namespace-prefixes.</p> + * + * @param name The feature name, as a complete URI. + * @param value The requested feature value. + * @exception SAXNotRecognizedException If the feature + * can't be assigned or retrieved. + * @exception SAXNotSupportedException If the feature + * can't be assigned that value. + * @see org.xml.sax.XMLReader#setFeature + */ + public void setFeature (String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if (name.equals(NAMESPACES)) { + checkNotParsing("feature", name); + namespaces = value; + if (!namespaces && !prefixes) { + prefixes = true; + } + } else if (name.equals(NAMESPACE_PREFIXES)) { + checkNotParsing("feature", name); + prefixes = value; + if (!prefixes && !namespaces) { + namespaces = true; + } + } else if (name.equals(XMLNS_URIs)) { + checkNotParsing("feature", name); + uris = value; + } else { + throw new SAXNotRecognizedException("Feature: " + name); + } + } + + + /** + * Check a parser feature flag. + * + * <p>The only features recognized are namespaces and + * namespace-prefixes.</p> + * + * @param name The feature name, as a complete URI. + * @return The current feature value. + * @exception SAXNotRecognizedException If the feature + * value can't be assigned or retrieved. + * @exception SAXNotSupportedException If the + * feature is not currently readable. + * @see org.xml.sax.XMLReader#setFeature + */ + public boolean getFeature (String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if (name.equals(NAMESPACES)) { + return namespaces; + } else if (name.equals(NAMESPACE_PREFIXES)) { + return prefixes; + } else if (name.equals(XMLNS_URIs)) { + return uris; + } else { + throw new SAXNotRecognizedException("Feature: " + name); + } + } + + + /** + * Set a parser property. + * + * <p>No properties are currently recognized.</p> + * + * @param name The property name. + * @param value The property value. + * @exception SAXNotRecognizedException If the property + * value can't be assigned or retrieved. + * @exception SAXNotSupportedException If the property + * can't be assigned that value. + * @see org.xml.sax.XMLReader#setProperty + */ + public void setProperty (String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + throw new SAXNotRecognizedException("Property: " + name); + } + + + /** + * Get a parser property. + * + * <p>No properties are currently recognized.</p> + * + * @param name The property name. + * @return The property value. + * @exception SAXNotRecognizedException If the property + * value can't be assigned or retrieved. + * @exception SAXNotSupportedException If the property + * value is not currently readable. + * @see org.xml.sax.XMLReader#getProperty + */ + public Object getProperty (String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + throw new SAXNotRecognizedException("Property: " + name); + } + + + /** + * Set the entity resolver. + * + * @param resolver The new entity resolver. + * @see org.xml.sax.XMLReader#setEntityResolver + */ + public void setEntityResolver (EntityResolver resolver) + { + entityResolver = resolver; + } + + + /** + * Return the current entity resolver. + * + * @return The current entity resolver, or null if none was supplied. + * @see org.xml.sax.XMLReader#getEntityResolver + */ + public EntityResolver getEntityResolver () + { + return entityResolver; + } + + + /** + * Set the DTD handler. + * + * @param handler the new DTD handler + * @see org.xml.sax.XMLReader#setEntityResolver + */ + public void setDTDHandler (DTDHandler handler) + { + dtdHandler = handler; + } + + + /** + * Return the current DTD handler. + * + * @return the current DTD handler, or null if none was supplied + * @see org.xml.sax.XMLReader#getEntityResolver + */ + public DTDHandler getDTDHandler () + { + return dtdHandler; + } + + + /** + * Set the content handler. + * + * @param handler the new content handler + * @see org.xml.sax.XMLReader#setEntityResolver + */ + public void setContentHandler (ContentHandler handler) + { + contentHandler = handler; + } + + + /** + * Return the current content handler. + * + * @return The current content handler, or null if none was supplied. + * @see org.xml.sax.XMLReader#getEntityResolver + */ + public ContentHandler getContentHandler () + { + return contentHandler; + } + + + /** + * Set the error handler. + * + * @param handler The new error handler. + * @see org.xml.sax.XMLReader#setEntityResolver + */ + public void setErrorHandler (ErrorHandler handler) + { + errorHandler = handler; + } + + + /** + * Return the current error handler. + * + * @return The current error handler, or null if none was supplied. + * @see org.xml.sax.XMLReader#getEntityResolver + */ + public ErrorHandler getErrorHandler () + { + return errorHandler; + } + + + /** + * Parse an XML document. + * + * @param systemId The absolute URL of the document. + * @exception java.io.IOException If there is a problem reading + * the raw content of the document. + * @exception SAXException If there is a problem + * processing the document. + * @see #parse(org.xml.sax.InputSource) + * @see org.xml.sax.Parser#parse(java.lang.String) + */ + public void parse (String systemId) + throws IOException, SAXException + { + parse(new InputSource(systemId)); + } + + + /** + * Parse an XML document. + * + * @param input An input source for the document. + * @exception java.io.IOException If there is a problem reading + * the raw content of the document. + * @exception SAXException If there is a problem + * processing the document. + * @see #parse(java.lang.String) + * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource) + */ + public void parse (InputSource input) + throws IOException, SAXException + { + if (parsing) { + throw new SAXException("Parser is already in use"); + } + setupParser(); + parsing = true; + try { + parser.parse(input); + } finally { + parsing = false; + } + parsing = false; + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.DocumentHandler. + //////////////////////////////////////////////////////////////////// + + + /** + * Adapter implementation method; do not call. + * Adapt a SAX1 document locator event. + * + * @param locator A document locator. + * @see org.xml.sax.ContentHandler#setDocumentLocator + */ + public void setDocumentLocator (Locator locator) + { + this.locator = locator; + if (contentHandler != null) { + contentHandler.setDocumentLocator(locator); + } + } + + + /** + * Adapter implementation method; do not call. + * Adapt a SAX1 start document event. + * + * @exception SAXException The client may raise a + * processing exception. + * @see org.xml.sax.DocumentHandler#startDocument + */ + public void startDocument () + throws SAXException + { + if (contentHandler != null) { + contentHandler.startDocument(); + } + } + + + /** + * Adapter implementation method; do not call. + * Adapt a SAX1 end document event. + * + * @exception SAXException The client may raise a + * processing exception. + * @see org.xml.sax.DocumentHandler#endDocument + */ + public void endDocument () + throws SAXException + { + if (contentHandler != null) { + contentHandler.endDocument(); + } + } + + + /** + * Adapter implementation method; do not call. + * Adapt a SAX1 startElement event. + * + * <p>If necessary, perform Namespace processing.</p> + * + * @param qName The qualified (prefixed) name. + * @param qAtts The XML attribute list (with qnames). + * @exception SAXException The client may raise a + * processing exception. + */ + public void startElement (String qName, AttributeList qAtts) + throws SAXException + { + // These are exceptions from the + // first pass; they should be + // ignored if there's a second pass, + // but reported otherwise. + Vector exceptions = null; + + // If we're not doing Namespace + // processing, dispatch this quickly. + if (!namespaces) { + if (contentHandler != null) { + attAdapter.setAttributeList(qAtts); + contentHandler.startElement("", "", qName.intern(), + attAdapter); + } + return; + } + + + // OK, we're doing Namespace processing. + nsSupport.pushContext(); + int length = qAtts.getLength(); + + // First pass: handle NS decls + for (int i = 0; i < length; i++) { + String attQName = qAtts.getName(i); + + if (!attQName.startsWith("xmlns")) + continue; + // Could be a declaration... + String prefix; + int n = attQName.indexOf(':'); + + // xmlns=... + if (n == -1 && attQName.length () == 5) { + prefix = ""; + } else if (n != 5) { + // XML namespaces spec doesn't discuss "xmlnsf:oo" + // (and similarly named) attributes ... at most, warn + continue; + } else // xmlns:foo=... + prefix = attQName.substring(n+1); + + String value = qAtts.getValue(i); + if (!nsSupport.declarePrefix(prefix, value)) { + reportError("Illegal Namespace prefix: " + prefix); + continue; + } + if (contentHandler != null) + contentHandler.startPrefixMapping(prefix, value); + } + + // Second pass: copy all relevant + // attributes into the SAX2 AttributeList + // using updated prefix bindings + atts.clear(); + for (int i = 0; i < length; i++) { + String attQName = qAtts.getName(i); + String type = qAtts.getType(i); + String value = qAtts.getValue(i); + + // Declaration? + if (attQName.startsWith("xmlns")) { + String prefix; + int n = attQName.indexOf(':'); + + if (n == -1 && attQName.length () == 5) { + prefix = ""; + } else if (n != 5) { + // XML namespaces spec doesn't discuss "xmlnsf:oo" + // (and similarly named) attributes ... ignore + prefix = null; + } else { + prefix = attQName.substring(6); + } + // Yes, decl: report or prune + if (prefix != null) { + if (prefixes) { + if (uris) + // note funky case: localname can be null + // when declaring the default prefix, and + // yet the uri isn't null. + atts.addAttribute (nsSupport.XMLNS, prefix, + attQName.intern(), type, value); + else + atts.addAttribute ("", "", + attQName.intern(), type, value); + } + continue; + } + } + + // Not a declaration -- report + try { + String attName[] = processName(attQName, true, true); + atts.addAttribute(attName[0], attName[1], attName[2], + type, value); + } catch (SAXException e) { + if (exceptions == null) + exceptions = new Vector(); + exceptions.addElement(e); + atts.addAttribute("", attQName, attQName, type, value); + } + } + + // now handle the deferred exception reports + if (exceptions != null && errorHandler != null) { + for (int i = 0; i < exceptions.size(); i++) + errorHandler.error((SAXParseException) + (exceptions.elementAt(i))); + } + + // OK, finally report the event. + if (contentHandler != null) { + String name[] = processName(qName, false, false); + contentHandler.startElement(name[0], name[1], name[2], atts); + } + } + + + /** + * Adapter implementation method; do not call. + * Adapt a SAX1 end element event. + * + * @param qName The qualified (prefixed) name. + * @exception SAXException The client may raise a + * processing exception. + * @see org.xml.sax.DocumentHandler#endElement + */ + public void endElement (String qName) + throws SAXException + { + // If we're not doing Namespace + // processing, dispatch this quickly. + if (!namespaces) { + if (contentHandler != null) { + contentHandler.endElement("", "", qName.intern()); + } + return; + } + + // Split the name. + String names[] = processName(qName, false, false); + if (contentHandler != null) { + contentHandler.endElement(names[0], names[1], names[2]); + Enumeration prefixes = nsSupport.getDeclaredPrefixes(); + while (prefixes.hasMoreElements()) { + String prefix = (String)prefixes.nextElement(); + contentHandler.endPrefixMapping(prefix); + } + } + nsSupport.popContext(); + } + + + /** + * Adapter implementation method; do not call. + * Adapt a SAX1 characters event. + * + * @param ch An array of characters. + * @param start The starting position in the array. + * @param length The number of characters to use. + * @exception SAXException The client may raise a + * processing exception. + * @see org.xml.sax.DocumentHandler#characters + */ + public void characters (char ch[], int start, int length) + throws SAXException + { + if (contentHandler != null) { + contentHandler.characters(ch, start, length); + } + } + + + /** + * Adapter implementation method; do not call. + * Adapt a SAX1 ignorable whitespace event. + * + * @param ch An array of characters. + * @param start The starting position in the array. + * @param length The number of characters to use. + * @exception SAXException The client may raise a + * processing exception. + * @see org.xml.sax.DocumentHandler#ignorableWhitespace + */ + public void ignorableWhitespace (char ch[], int start, int length) + throws SAXException + { + if (contentHandler != null) { + contentHandler.ignorableWhitespace(ch, start, length); + } + } + + + /** + * Adapter implementation method; do not call. + * Adapt a SAX1 processing instruction event. + * + * @param target The processing instruction target. + * @param data The remainder of the processing instruction + * @exception SAXException The client may raise a + * processing exception. + * @see org.xml.sax.DocumentHandler#processingInstruction + */ + public void processingInstruction (String target, String data) + throws SAXException + { + if (contentHandler != null) { + contentHandler.processingInstruction(target, data); + } + } + + + + //////////////////////////////////////////////////////////////////// + // Internal utility methods. + //////////////////////////////////////////////////////////////////// + + + /** + * Initialize the parser before each run. + */ + private void setupParser () + { + // catch an illegal "nonsense" state. + if (!prefixes && !namespaces) + throw new IllegalStateException (); + + nsSupport.reset(); + if (uris) + nsSupport.setNamespaceDeclUris (true); + + if (entityResolver != null) { + parser.setEntityResolver(entityResolver); + } + if (dtdHandler != null) { + parser.setDTDHandler(dtdHandler); + } + if (errorHandler != null) { + parser.setErrorHandler(errorHandler); + } + parser.setDocumentHandler(this); + locator = null; + } + + + /** + * Process a qualified (prefixed) name. + * + * <p>If the name has an undeclared prefix, use only the qname + * and make an ErrorHandler.error callback in case the app is + * interested.</p> + * + * @param qName The qualified (prefixed) name. + * @param isAttribute true if this is an attribute name. + * @return The name split into three parts. + * @exception SAXException The client may throw + * an exception if there is an error callback. + */ + private String [] processName (String qName, boolean isAttribute, + boolean useException) + throws SAXException + { + String parts[] = nsSupport.processName(qName, nameParts, + isAttribute); + if (parts == null) { + if (useException) + throw makeException("Undeclared prefix: " + qName); + reportError("Undeclared prefix: " + qName); + parts = new String[3]; + parts[0] = parts[1] = ""; + parts[2] = qName.intern(); + } + return parts; + } + + + /** + * Report a non-fatal error. + * + * @param message The error message. + * @exception SAXException The client may throw + * an exception. + */ + void reportError (String message) + throws SAXException + { + if (errorHandler != null) + errorHandler.error(makeException(message)); + } + + + /** + * Construct an exception for the current context. + * + * @param message The error message. + */ + private SAXParseException makeException (String message) + { + if (locator != null) { + return new SAXParseException(message, locator); + } else { + return new SAXParseException(message, null, null, -1, -1); + } + } + + + /** + * Throw an exception if we are parsing. + * + * <p>Use this method to detect illegal feature or + * property changes.</p> + * + * @param type The type of thing (feature or property). + * @param name The feature or property name. + * @exception SAXNotSupportedException If a + * document is currently being parsed. + */ + private void checkNotParsing (String type, String name) + throws SAXNotSupportedException + { + if (parsing) { + throw new SAXNotSupportedException("Cannot change " + + type + ' ' + + name + " while parsing"); + + } + } + + + + //////////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////////// + + private NamespaceSupport nsSupport; + private AttributeListAdapter attAdapter; + + private boolean parsing = false; + private String nameParts[] = new String[3]; + + private Parser parser = null; + + private AttributesImpl atts = null; + + // Features + private boolean namespaces = true; + private boolean prefixes = false; + private boolean uris = false; + + // Properties + + // Handlers + Locator locator; + + EntityResolver entityResolver = null; + DTDHandler dtdHandler = null; + ContentHandler contentHandler = null; + ErrorHandler errorHandler = null; + + + + //////////////////////////////////////////////////////////////////// + // Inner class to wrap an AttributeList when not doing NS proc. + //////////////////////////////////////////////////////////////////// + + + /** + * Adapt a SAX1 AttributeList as a SAX2 Attributes object. + * + * <p>This class is in the Public Domain, and comes with NO + * WARRANTY of any kind.</p> + * + * <p>This wrapper class is used only when Namespace support + * is disabled -- it provides pretty much a direct mapping + * from SAX1 to SAX2, except that names and types are + * interned whenever requested.</p> + */ + final class AttributeListAdapter implements Attributes + { + + /** + * Construct a new adapter. + */ + AttributeListAdapter () + { + } + + + /** + * Set the embedded AttributeList. + * + * <p>This method must be invoked before any of the others + * can be used.</p> + * + * @param The SAX1 attribute list (with qnames). + */ + void setAttributeList (AttributeList qAtts) + { + this.qAtts = qAtts; + } + + + /** + * Return the length of the attribute list. + * + * @return The number of attributes in the list. + * @see org.xml.sax.Attributes#getLength + */ + public int getLength () + { + return qAtts.getLength(); + } + + + /** + * Return the Namespace URI of the specified attribute. + * + * @param The attribute's index. + * @return Always the empty string. + * @see org.xml.sax.Attributes#getURI + */ + public String getURI (int i) + { + return ""; + } + + + /** + * Return the local name of the specified attribute. + * + * @param The attribute's index. + * @return Always the empty string. + * @see org.xml.sax.Attributes#getLocalName + */ + public String getLocalName (int i) + { + return ""; + } + + + /** + * Return the qualified (prefixed) name of the specified attribute. + * + * @param The attribute's index. + * @return The attribute's qualified name, internalized. + */ + public String getQName (int i) + { + return qAtts.getName(i).intern(); + } + + + /** + * Return the type of the specified attribute. + * + * @param The attribute's index. + * @return The attribute's type as an internalized string. + */ + public String getType (int i) + { + return qAtts.getType(i).intern(); + } + + + /** + * Return the value of the specified attribute. + * + * @param The attribute's index. + * @return The attribute's value. + */ + public String getValue (int i) + { + return qAtts.getValue(i); + } + + + /** + * Look up an attribute index by Namespace name. + * + * @param uri The Namespace URI or the empty string. + * @param localName The local name. + * @return The attributes index, or -1 if none was found. + * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String) + */ + public int getIndex (String uri, String localName) + { + return -1; + } + + + /** + * Look up an attribute index by qualified (prefixed) name. + * + * @param qName The qualified name. + * @return The attributes index, or -1 if none was found. + * @see org.xml.sax.Attributes#getIndex(java.lang.String) + */ + public int getIndex (String qName) + { + int max = atts.getLength(); + for (int i = 0; i < max; i++) { + if (qAtts.getName(i).equals(qName)) { + return i; + } + } + return -1; + } + + + /** + * Look up the type of an attribute by Namespace name. + * + * @param uri The Namespace URI + * @param localName The local name. + * @return The attribute's type as an internalized string. + */ + public String getType (String uri, String localName) + { + return null; + } + + + /** + * Look up the type of an attribute by qualified (prefixed) name. + * + * @param qName The qualified name. + * @return The attribute's type as an internalized string. + */ + public String getType (String qName) + { + return qAtts.getType(qName).intern(); + } + + + /** + * Look up the value of an attribute by Namespace name. + * + * @param uri The Namespace URI + * @param localName The local name. + * @return The attribute's value. + */ + public String getValue (String uri, String localName) + { + return null; + } + + + /** + * Look up the value of an attribute by qualified (prefixed) name. + * + * @param qName The qualified name. + * @return The attribute's value. + */ + public String getValue (String qName) + { + return qAtts.getValue(qName); + } + + private AttributeList qAtts; + } +} + +// end of ParserAdapter.java diff --git a/xml/src/main/java/org/xml/sax/helpers/ParserFactory.java b/xml/src/main/java/org/xml/sax/helpers/ParserFactory.java new file mode 100644 index 0000000..ffe2a60 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/ParserFactory.java @@ -0,0 +1,133 @@ +// SAX parser factory. +// http://www.saxproject.org +// No warranty; no copyright -- use this as you will. +// $Id: ParserFactory.java,v 1.7 2002/01/30 20:52:36 dbrownell Exp $ + +package org.xml.sax.helpers; + +import java.lang.ClassNotFoundException; +import java.lang.IllegalAccessException; +import java.lang.InstantiationException; +import java.lang.SecurityException; +import java.lang.ClassCastException; + +import org.xml.sax.Parser; + + +/** + * Java-specific class for dynamically loading SAX parsers. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p><strong>Note:</strong> This class is designed to work with the now-deprecated + * SAX1 {@link org.xml.sax.Parser Parser} class. SAX2 applications should use + * {@link org.xml.sax.helpers.XMLReaderFactory XMLReaderFactory} instead.</p> + * + * <p>ParserFactory is not part of the platform-independent definition + * of SAX; it is an additional convenience class designed + * specifically for Java XML application writers. SAX applications + * can use the static methods in this class to allocate a SAX parser + * dynamically at run-time based either on the value of the + * `org.xml.sax.parser' system property or on a string containing the class + * name.</p> + * + * <p>Note that the application still requires an XML parser that + * implements SAX1.</p> + * + * @deprecated This class works with the deprecated + * {@link org.xml.sax.Parser Parser} + * interface. + * @since SAX 1.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + */ +public class ParserFactory { + + + /** + * Private null constructor. + */ + private ParserFactory () + { + } + + + /** + * Create a new SAX parser using the `org.xml.sax.parser' system property. + * + * <p>The named class must exist and must implement the + * {@link org.xml.sax.Parser Parser} interface.</p> + * + * @return the newly created parser. + * + * @exception java.lang.NullPointerException There is no value + * for the `org.xml.sax.parser' system property. + * @exception java.lang.ClassNotFoundException The SAX parser + * class was not found (check your CLASSPATH). + * @exception IllegalAccessException The SAX parser class was + * found, but you do not have permission to load + * it. + * @exception InstantiationException The SAX parser class was + * found but could not be instantiated. + * @exception java.lang.ClassCastException The SAX parser class + * was found and instantiated, but does not implement + * org.xml.sax.Parser. + * @see #makeParser(java.lang.String) + * @see org.xml.sax.Parser + */ + public static Parser makeParser () + throws ClassNotFoundException, + IllegalAccessException, + InstantiationException, + NullPointerException, + ClassCastException + { + String className = System.getProperty("org.xml.sax.parser"); + if (className == null) { + throw new NullPointerException("No value for sax.parser property"); + } else { + return makeParser(className); + } + } + + + /** + * Create a new SAX parser object using the class name provided. + * + * <p>The named class must exist and must implement the + * {@link org.xml.sax.Parser Parser} interface.</p> + * + * @return the newly created parser. + * + * @param className A string containing the name of the + * SAX parser class. + * @exception java.lang.ClassNotFoundException The SAX parser + * class was not found (check your CLASSPATH). + * @exception IllegalAccessException The SAX parser class was + * found, but you do not have permission to load + * it. + * @exception InstantiationException The SAX parser class was + * found but could not be instantiated. + * @exception java.lang.ClassCastException The SAX parser class + * was found and instantiated, but does not implement + * org.xml.sax.Parser. + * @see #makeParser() + * @see org.xml.sax.Parser + */ + public static Parser makeParser (String className) + throws ClassNotFoundException, + IllegalAccessException, + InstantiationException, + ClassCastException + { + return (Parser) NewInstance.newInstance ( + NewInstance.getClassLoader (), className); + } + +} + diff --git a/xml/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java b/xml/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java new file mode 100644 index 0000000..68e2579 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java @@ -0,0 +1,715 @@ +// XMLFilterImpl.java - base SAX2 filter implementation. +// http://www.saxproject.org +// Written by David Megginson +// NO WARRANTY! This class is in the Public Domain. +// $Id: XMLFilterImpl.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $ + +package org.xml.sax.helpers; + +import java.io.IOException; + +import org.xml.sax.XMLReader; +import org.xml.sax.XMLFilter; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; +import org.xml.sax.EntityResolver; +import org.xml.sax.DTDHandler; +import org.xml.sax.ContentHandler; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.SAXNotRecognizedException; + + +/** + * Base class for deriving an XML filter. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class is designed to sit between an {@link org.xml.sax.XMLReader + * XMLReader} and the client application's event handlers. By default, it + * does nothing but pass requests up to the reader and events + * on to the handlers unmodified, but subclasses can override + * specific methods to modify the event stream or the configuration + * requests as they pass through.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.XMLFilter + * @see org.xml.sax.XMLReader + * @see org.xml.sax.EntityResolver + * @see org.xml.sax.DTDHandler + * @see org.xml.sax.ContentHandler + * @see org.xml.sax.ErrorHandler + */ +public class XMLFilterImpl + implements XMLFilter, EntityResolver, DTDHandler, ContentHandler, ErrorHandler +{ + + + //////////////////////////////////////////////////////////////////// + // Constructors. + //////////////////////////////////////////////////////////////////// + + + /** + * Construct an empty XML filter, with no parent. + * + * <p>This filter will have no parent: you must assign a parent + * before you start a parse or do any configuration with + * setFeature or setProperty, unless you use this as a pure event + * consumer rather than as an {@link XMLReader}.</p> + * + * @see org.xml.sax.XMLReader#setFeature + * @see org.xml.sax.XMLReader#setProperty + * @see #setParent + */ + public XMLFilterImpl () + { + super(); + } + + + /** + * Construct an XML filter with the specified parent. + * + * @param parent the XML reader from which this filter receives its events. + * + * @see #setParent + * @see #getParent + */ + public XMLFilterImpl (XMLReader parent) + { + super(); + setParent(parent); + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.XMLFilter. + //////////////////////////////////////////////////////////////////// + + + /** + * Set the parent reader. + * + * <p>This is the {@link org.xml.sax.XMLReader XMLReader} from which + * this filter will obtain its events and to which it will pass its + * configuration requests. The parent may itself be another filter.</p> + * + * <p>If there is no parent reader set, any attempt to parse + * or to set or get a feature or property will fail.</p> + * + * @param parent The parent XML reader. + * @see #getParent + */ + public void setParent (XMLReader parent) + { + this.parent = parent; + } + + + /** + * Get the parent reader. + * + * @return The parent XML reader, or null if none is set. + * @see #setParent + */ + public XMLReader getParent () + { + return parent; + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.XMLReader. + //////////////////////////////////////////////////////////////////// + + + /** + * Set the value of a feature. + * + * <p>This will always fail if the parent is null.</p> + * + * @param name The feature name. + * @param value The requested feature value. + * @exception org.xml.sax.SAXNotRecognizedException If the feature + * value can't be assigned or retrieved from the parent. + * @exception org.xml.sax.SAXNotSupportedException When the + * parent recognizes the feature name but + * cannot set the requested value. + */ + public void setFeature (String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if (parent != null) { + parent.setFeature(name, value); + } else { + throw new SAXNotRecognizedException("Feature: " + name); + } + } + + + /** + * Look up the value of a feature. + * + * <p>This will always fail if the parent is null.</p> + * + * @param name The feature name. + * @return The current value of the feature. + * @exception org.xml.sax.SAXNotRecognizedException If the feature + * value can't be assigned or retrieved from the parent. + * @exception org.xml.sax.SAXNotSupportedException When the + * parent recognizes the feature name but + * cannot determine its value at this time. + */ + public boolean getFeature (String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if (parent != null) { + return parent.getFeature(name); + } else { + throw new SAXNotRecognizedException("Feature: " + name); + } + } + + + /** + * Set the value of a property. + * + * <p>This will always fail if the parent is null.</p> + * + * @param name The property name. + * @param value The requested property value. + * @exception org.xml.sax.SAXNotRecognizedException If the property + * value can't be assigned or retrieved from the parent. + * @exception org.xml.sax.SAXNotSupportedException When the + * parent recognizes the property name but + * cannot set the requested value. + */ + public void setProperty (String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if (parent != null) { + parent.setProperty(name, value); + } else { + throw new SAXNotRecognizedException("Property: " + name); + } + } + + + /** + * Look up the value of a property. + * + * @param name The property name. + * @return The current value of the property. + * @exception org.xml.sax.SAXNotRecognizedException If the property + * value can't be assigned or retrieved from the parent. + * @exception org.xml.sax.SAXNotSupportedException When the + * parent recognizes the property name but + * cannot determine its value at this time. + */ + public Object getProperty (String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if (parent != null) { + return parent.getProperty(name); + } else { + throw new SAXNotRecognizedException("Property: " + name); + } + } + + + /** + * Set the entity resolver. + * + * @param resolver The new entity resolver. + */ + public void setEntityResolver (EntityResolver resolver) + { + entityResolver = resolver; + } + + + /** + * Get the current entity resolver. + * + * @return The current entity resolver, or null if none was set. + */ + public EntityResolver getEntityResolver () + { + return entityResolver; + } + + + /** + * Set the DTD event handler. + * + * @param handler the new DTD handler + */ + public void setDTDHandler (DTDHandler handler) + { + dtdHandler = handler; + } + + + /** + * Get the current DTD event handler. + * + * @return The current DTD handler, or null if none was set. + */ + public DTDHandler getDTDHandler () + { + return dtdHandler; + } + + + /** + * Set the content event handler. + * + * @param handler the new content handler + */ + public void setContentHandler (ContentHandler handler) + { + contentHandler = handler; + } + + + /** + * Get the content event handler. + * + * @return The current content handler, or null if none was set. + */ + public ContentHandler getContentHandler () + { + return contentHandler; + } + + + /** + * Set the error event handler. + * + * @param handler the new error handler + */ + public void setErrorHandler (ErrorHandler handler) + { + errorHandler = handler; + } + + + /** + * Get the current error event handler. + * + * @return The current error handler, or null if none was set. + */ + public ErrorHandler getErrorHandler () + { + return errorHandler; + } + + + /** + * Parse a document. + * + * @param input The input source for the document entity. + * @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. + */ + public void parse (InputSource input) + throws SAXException, IOException + { + setupParse(); + parent.parse(input); + } + + + /** + * Parse a document. + * + * @param systemId The system identifier as a fully-qualified 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. + */ + public void parse (String systemId) + throws SAXException, IOException + { + parse(new InputSource(systemId)); + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.EntityResolver. + //////////////////////////////////////////////////////////////////// + + + /** + * Filter an external entity resolution. + * + * @param publicId The entity's public identifier, or null. + * @param systemId The entity's system identifier. + * @return A new InputSource or null for the default. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + * @exception java.io.IOException The client may throw an + * I/O-related exception while obtaining the + * new InputSource. + */ + public InputSource resolveEntity (String publicId, String systemId) + throws SAXException, IOException + { + if (entityResolver != null) { + return entityResolver.resolveEntity(publicId, systemId); + } else { + return null; + } + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.DTDHandler. + //////////////////////////////////////////////////////////////////// + + + /** + * Filter a notation declaration event. + * + * @param name The notation name. + * @param publicId The notation's public identifier, or null. + * @param systemId The notation's system identifier, or null. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void notationDecl (String name, String publicId, String systemId) + throws SAXException + { + if (dtdHandler != null) { + dtdHandler.notationDecl(name, publicId, systemId); + } + } + + + /** + * Filter an unparsed entity declaration event. + * + * @param name The entity name. + * @param publicId The entity's public identifier, or null. + * @param systemId The entity's system identifier, or null. + * @param notationName The name of the associated notation. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void unparsedEntityDecl (String name, String publicId, + String systemId, String notationName) + throws SAXException + { + if (dtdHandler != null) { + dtdHandler.unparsedEntityDecl(name, publicId, systemId, + notationName); + } + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.ContentHandler. + //////////////////////////////////////////////////////////////////// + + + /** + * Filter a new document locator event. + * + * @param locator The document locator. + */ + public void setDocumentLocator (Locator locator) + { + this.locator = locator; + if (contentHandler != null) { + contentHandler.setDocumentLocator(locator); + } + } + + + /** + * Filter a start document event. + * + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void startDocument () + throws SAXException + { + if (contentHandler != null) { + contentHandler.startDocument(); + } + } + + + /** + * Filter an end document event. + * + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void endDocument () + throws SAXException + { + if (contentHandler != null) { + contentHandler.endDocument(); + } + } + + + /** + * Filter a start Namespace prefix mapping event. + * + * @param prefix The Namespace prefix. + * @param uri The Namespace URI. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void startPrefixMapping (String prefix, String uri) + throws SAXException + { + if (contentHandler != null) { + contentHandler.startPrefixMapping(prefix, uri); + } + } + + + /** + * Filter an end Namespace prefix mapping event. + * + * @param prefix The Namespace prefix. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void endPrefixMapping (String prefix) + throws SAXException + { + if (contentHandler != null) { + contentHandler.endPrefixMapping(prefix); + } + } + + + /** + * Filter a start element event. + * + * @param uri The element's Namespace URI, or the empty string. + * @param localName The element's local name, or the empty string. + * @param qName The element's qualified (prefixed) name, or the empty + * string. + * @param atts The element's attributes. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void startElement (String uri, String localName, String qName, + Attributes atts) + throws SAXException + { + if (contentHandler != null) { + contentHandler.startElement(uri, localName, qName, atts); + } + } + + + /** + * Filter an end element event. + * + * @param uri The element's Namespace URI, or the empty string. + * @param localName The element's local name, or the empty string. + * @param qName The element's qualified (prefixed) name, or the empty + * string. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void endElement (String uri, String localName, String qName) + throws SAXException + { + if (contentHandler != null) { + contentHandler.endElement(uri, localName, qName); + } + } + + + /** + * Filter a character data event. + * + * @param ch An array of characters. + * @param start The starting position in the array. + * @param length The number of characters to use from the array. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void characters (char ch[], int start, int length) + throws SAXException + { + if (contentHandler != null) { + contentHandler.characters(ch, start, length); + } + } + + + /** + * Filter an ignorable whitespace event. + * + * @param ch An array of characters. + * @param start The starting position in the array. + * @param length The number of characters to use from the array. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void ignorableWhitespace (char ch[], int start, int length) + throws SAXException + { + if (contentHandler != null) { + contentHandler.ignorableWhitespace(ch, start, length); + } + } + + + /** + * Filter a processing instruction event. + * + * @param target The processing instruction target. + * @param data The text following the target. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void processingInstruction (String target, String data) + throws SAXException + { + if (contentHandler != null) { + contentHandler.processingInstruction(target, data); + } + } + + + /** + * Filter a skipped entity event. + * + * @param name The name of the skipped entity. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void skippedEntity (String name) + throws SAXException + { + if (contentHandler != null) { + contentHandler.skippedEntity(name); + } + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.ErrorHandler. + //////////////////////////////////////////////////////////////////// + + + /** + * Filter a warning event. + * + * @param e The warning as an exception. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void warning (SAXParseException e) + throws SAXException + { + if (errorHandler != null) { + errorHandler.warning(e); + } + } + + + /** + * Filter an error event. + * + * @param e The error as an exception. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void error (SAXParseException e) + throws SAXException + { + if (errorHandler != null) { + errorHandler.error(e); + } + } + + + /** + * Filter a fatal error event. + * + * @param e The error as an exception. + * @exception org.xml.sax.SAXException The client may throw + * an exception during processing. + */ + public void fatalError (SAXParseException e) + throws SAXException + { + if (errorHandler != null) { + errorHandler.fatalError(e); + } + } + + + + //////////////////////////////////////////////////////////////////// + // Internal methods. + //////////////////////////////////////////////////////////////////// + + + /** + * Set up before a parse. + * + * <p>Before every parse, check whether the parent is + * non-null, and re-register the filter for all of the + * events.</p> + */ + private void setupParse () + { + if (parent == null) { + throw new NullPointerException("No parent for filter"); + } + parent.setEntityResolver(this); + parent.setDTDHandler(this); + parent.setContentHandler(this); + parent.setErrorHandler(this); + } + + + + //////////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////////// + + private XMLReader parent = null; + private Locator locator = null; + private EntityResolver entityResolver = null; + private DTDHandler dtdHandler = null; + private ContentHandler contentHandler = null; + private ErrorHandler errorHandler = null; + +} + +// end of XMLFilterImpl.java diff --git a/xml/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java b/xml/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java new file mode 100644 index 0000000..cc8f431 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java @@ -0,0 +1,538 @@ +// XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser +// http://www.saxproject.org +// Written by David Megginson +// NO WARRANTY! This class is in the public domain. +// $Id: XMLReaderAdapter.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $ + +package org.xml.sax.helpers; + +import java.io.IOException; +import java.util.Locale; + +import org.xml.sax.Parser; // deprecated +import org.xml.sax.Locator; +import org.xml.sax.InputSource; +import org.xml.sax.AttributeList; // deprecated +import org.xml.sax.EntityResolver; +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; // deprecated +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; + +import org.xml.sax.XMLReader; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXNotSupportedException; + + +/** + * Adapt a SAX2 XMLReader as a SAX1 Parser. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader} + * and makes it act as a SAX1 {@link org.xml.sax.Parser Parser}. The XMLReader + * must support a true value for the + * http://xml.org/sax/features/namespace-prefixes property or parsing will fail + * with a {@link org.xml.sax.SAXException SAXException}; if the XMLReader + * supports a false value for the http://xml.org/sax/features/namespaces + * property, that will also be used to improve efficiency.</p> + * + * @since SAX 2.0 + * @author David Megginson + * @version 2.0.1 (sax2r2) + * @see org.xml.sax.Parser + * @see org.xml.sax.XMLReader + */ +public class XMLReaderAdapter implements Parser, ContentHandler +{ + + + //////////////////////////////////////////////////////////////////// + // Constructor. + //////////////////////////////////////////////////////////////////// + + + /** + * Create a new adapter. + * + * <p>Use the "org.xml.sax.driver" property to locate the SAX2 + * driver to embed.</p> + * + * @exception org.xml.sax.SAXException If the embedded driver + * cannot be instantiated or if the + * org.xml.sax.driver property is not specified. + */ + public XMLReaderAdapter () + throws SAXException + { + setup(XMLReaderFactory.createXMLReader()); + } + + + /** + * Create a new adapter. + * + * <p>Create a new adapter, wrapped around a SAX2 XMLReader. + * The adapter will make the XMLReader act like a SAX1 + * Parser.</p> + * + * @param xmlReader The SAX2 XMLReader to wrap. + * @exception java.lang.NullPointerException If the argument is null. + */ + public XMLReaderAdapter (XMLReader xmlReader) + { + setup(xmlReader); + } + + + + /** + * Internal setup. + * + * @param xmlReader The embedded XMLReader. + */ + private void setup (XMLReader xmlReader) + { + if (xmlReader == null) { + throw new NullPointerException("XMLReader must not be null"); + } + this.xmlReader = xmlReader; + qAtts = new AttributesAdapter(); + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.Parser. + //////////////////////////////////////////////////////////////////// + + + /** + * Set the locale for error reporting. + * + * <p>This is not supported in SAX2, and will always throw + * an exception.</p> + * + * @param locale the locale for error reporting. + * @see org.xml.sax.Parser#setLocale + * @exception org.xml.sax.SAXException Thrown unless overridden. + */ + public void setLocale (Locale locale) + throws SAXException + { + throw new SAXNotSupportedException("setLocale not supported"); + } + + + /** + * Register the entity resolver. + * + * @param resolver The new resolver. + * @see org.xml.sax.Parser#setEntityResolver + */ + public void setEntityResolver (EntityResolver resolver) + { + xmlReader.setEntityResolver(resolver); + } + + + /** + * Register the DTD event handler. + * + * @param handler The new DTD event handler. + * @see org.xml.sax.Parser#setDTDHandler + */ + public void setDTDHandler (DTDHandler handler) + { + xmlReader.setDTDHandler(handler); + } + + + /** + * Register the SAX1 document event handler. + * + * <p>Note that the SAX1 document handler has no Namespace + * support.</p> + * + * @param handler The new SAX1 document event handler. + * @see org.xml.sax.Parser#setDocumentHandler + */ + public void setDocumentHandler (DocumentHandler handler) + { + documentHandler = handler; + } + + + /** + * Register the error event handler. + * + * @param handler The new error event handler. + * @see org.xml.sax.Parser#setErrorHandler + */ + public void setErrorHandler (ErrorHandler handler) + { + xmlReader.setErrorHandler(handler); + } + + + /** + * Parse the document. + * + * <p>This method will throw an exception if the embedded + * XMLReader does not support the + * http://xml.org/sax/features/namespace-prefixes property.</p> + * + * @param systemId The absolute URL of the document. + * @exception java.io.IOException If there is a problem reading + * the raw content of the document. + * @exception org.xml.sax.SAXException If there is a problem + * processing the document. + * @see #parse(org.xml.sax.InputSource) + * @see org.xml.sax.Parser#parse(java.lang.String) + */ + public void parse (String systemId) + throws IOException, SAXException + { + parse(new InputSource(systemId)); + } + + + /** + * Parse the document. + * + * <p>This method will throw an exception if the embedded + * XMLReader does not support the + * http://xml.org/sax/features/namespace-prefixes property.</p> + * + * @param input An input source for the document. + * @exception java.io.IOException If there is a problem reading + * the raw content of the document. + * @exception org.xml.sax.SAXException If there is a problem + * processing the document. + * @see #parse(java.lang.String) + * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource) + */ + public void parse (InputSource input) + throws IOException, SAXException + { + setupXMLReader(); + xmlReader.parse(input); + } + + + /** + * Set up the XML reader. + */ + private void setupXMLReader () + throws SAXException + { + xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); + try { + xmlReader.setFeature("http://xml.org/sax/features/namespaces", + false); + } catch (SAXException e) { + // NO OP: it's just extra information, and we can ignore it + } + xmlReader.setContentHandler(this); + } + + + + //////////////////////////////////////////////////////////////////// + // Implementation of org.xml.sax.ContentHandler. + //////////////////////////////////////////////////////////////////// + + + /** + * Set a document locator. + * + * @param locator The document locator. + * @see org.xml.sax.ContentHandler#setDocumentLocator + */ + public void setDocumentLocator (Locator locator) + { + if (documentHandler != null) + documentHandler.setDocumentLocator(locator); + } + + + /** + * Start document event. + * + * @exception org.xml.sax.SAXException The client may raise a + * processing exception. + * @see org.xml.sax.ContentHandler#startDocument + */ + public void startDocument () + throws SAXException + { + if (documentHandler != null) + documentHandler.startDocument(); + } + + + /** + * End document event. + * + * @exception org.xml.sax.SAXException The client may raise a + * processing exception. + * @see org.xml.sax.ContentHandler#endDocument + */ + public void endDocument () + throws SAXException + { + if (documentHandler != null) + documentHandler.endDocument(); + } + + + /** + * Adapt a SAX2 start prefix mapping event. + * + * @param prefix The prefix being mapped. + * @param uri The Namespace URI being mapped to. + * @see org.xml.sax.ContentHandler#startPrefixMapping + */ + public void startPrefixMapping (String prefix, String uri) + { + } + + + /** + * Adapt a SAX2 end prefix mapping event. + * + * @param prefix The prefix being mapped. + * @see org.xml.sax.ContentHandler#endPrefixMapping + */ + public void endPrefixMapping (String prefix) + { + } + + + /** + * Adapt a SAX2 start element event. + * + * @param uri The Namespace URI. + * @param localName The Namespace local name. + * @param qName The qualified (prefixed) name. + * @param atts The SAX2 attributes. + * @exception org.xml.sax.SAXException The client may raise a + * processing exception. + * @see org.xml.sax.ContentHandler#endDocument + */ + public void startElement (String uri, String localName, + String qName, Attributes atts) + throws SAXException + { + if (documentHandler != null) { + qAtts.setAttributes(atts); + documentHandler.startElement(qName, qAtts); + } + } + + + /** + * Adapt a SAX2 end element event. + * + * @param uri The Namespace URI. + * @param localName The Namespace local name. + * @param qName The qualified (prefixed) name. + * @exception org.xml.sax.SAXException The client may raise a + * processing exception. + * @see org.xml.sax.ContentHandler#endElement + */ + public void endElement (String uri, String localName, + String qName) + throws SAXException + { + if (documentHandler != null) + documentHandler.endElement(qName); + } + + + /** + * Adapt a SAX2 characters event. + * + * @param ch An array of characters. + * @param start The starting position in the array. + * @param length The number of characters to use. + * @exception org.xml.sax.SAXException The client may raise a + * processing exception. + * @see org.xml.sax.ContentHandler#characters + */ + public void characters (char ch[], int start, int length) + throws SAXException + { + if (documentHandler != null) + documentHandler.characters(ch, start, length); + } + + + /** + * Adapt a SAX2 ignorable whitespace event. + * + * @param ch An array of characters. + * @param start The starting position in the array. + * @param length The number of characters to use. + * @exception org.xml.sax.SAXException The client may raise a + * processing exception. + * @see org.xml.sax.ContentHandler#ignorableWhitespace + */ + public void ignorableWhitespace (char ch[], int start, int length) + throws SAXException + { + if (documentHandler != null) + documentHandler.ignorableWhitespace(ch, start, length); + } + + + /** + * Adapt a SAX2 processing instruction event. + * + * @param target The processing instruction target. + * @param data The remainder of the processing instruction + * @exception org.xml.sax.SAXException The client may raise a + * processing exception. + * @see org.xml.sax.ContentHandler#processingInstruction + */ + public void processingInstruction (String target, String data) + throws SAXException + { + if (documentHandler != null) + documentHandler.processingInstruction(target, data); + } + + + /** + * Adapt a SAX2 skipped entity event. + * + * @param name The name of the skipped entity. + * @see org.xml.sax.ContentHandler#skippedEntity + * @exception org.xml.sax.SAXException Throwable by subclasses. + */ + public void skippedEntity (String name) + throws SAXException + { + } + + + + //////////////////////////////////////////////////////////////////// + // Internal state. + //////////////////////////////////////////////////////////////////// + + XMLReader xmlReader; + DocumentHandler documentHandler; + AttributesAdapter qAtts; + + + + //////////////////////////////////////////////////////////////////// + // Internal class. + //////////////////////////////////////////////////////////////////// + + + /** + * Internal class to wrap a SAX2 Attributes object for SAX1. + */ + final class AttributesAdapter implements AttributeList + { + AttributesAdapter () + { + } + + + /** + * Set the embedded Attributes object. + * + * @param The embedded SAX2 Attributes. + */ + void setAttributes (Attributes attributes) + { + this.attributes = attributes; + } + + + /** + * Return the number of attributes. + * + * @return The length of the attribute list. + * @see org.xml.sax.AttributeList#getLength + */ + public int getLength () + { + return attributes.getLength(); + } + + + /** + * Return the qualified (prefixed) name of an attribute by position. + * + * @return The qualified name. + * @see org.xml.sax.AttributeList#getName + */ + public String getName (int i) + { + return attributes.getQName(i); + } + + + /** + * Return the type of an attribute by position. + * + * @return The type. + * @see org.xml.sax.AttributeList#getType(int) + */ + public String getType (int i) + { + return attributes.getType(i); + } + + + /** + * Return the value of an attribute by position. + * + * @return The value. + * @see org.xml.sax.AttributeList#getValue(int) + */ + public String getValue (int i) + { + return attributes.getValue(i); + } + + + /** + * Return the type of an attribute by qualified (prefixed) name. + * + * @return The type. + * @see org.xml.sax.AttributeList#getType(java.lang.String) + */ + public String getType (String qName) + { + return attributes.getType(qName); + } + + + /** + * Return the value of an attribute by qualified (prefixed) name. + * + * @return The value. + * @see org.xml.sax.AttributeList#getValue(java.lang.String) + */ + public String getValue (String qName) + { + return attributes.getValue(qName); + } + + private Attributes attributes; + } + +} + +// end of XMLReaderAdapter.java diff --git a/xml/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java b/xml/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java new file mode 100644 index 0000000..96151a1 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java @@ -0,0 +1,206 @@ +// XMLReaderFactory.java - factory for creating a new reader. +// http://www.saxproject.org +// Written by David Megginson +// and by David Brownell +// NO WARRANTY! This class is in the Public Domain. +// $Id: XMLReaderFactory.java,v 1.10 2002/04/22 01:00:13 dbrownell Exp $ + +package org.xml.sax.helpers; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import org.xml.sax.XMLReader; +import org.xml.sax.SAXException; + + +/** + * Factory for creating an XML reader. + * + * <blockquote> + * <em>This module, both source code and documentation, is in the + * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> + * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> + * for further information. + * </blockquote> + * + * <p>This class contains static methods for creating an XML reader + * from an explicit class name, or based on runtime defaults:</p> + * + * <pre> + * try { + * XMLReader myReader = XMLReaderFactory.createXMLReader(); + * } catch (SAXException e) { + * System.err.println(e.getMessage()); + * } + * </pre> + * + * <p><strong>Note to Distributions bundled with parsers:</strong> + * You should modify the implementation of the no-arguments + * <em>createXMLReader</em> to handle cases where the external + * configuration mechanisms aren't set up. That method should do its + * best to return a parser when one is in the class path, even when + * nothing bound its class name to <code>org.xml.sax.driver</code> so + * those configuration mechanisms would see it.</p> + * + * @since SAX 2.0 + * @author David Megginson, David Brownell + * @version 2.0.1 (sax2r2) + */ +final public class XMLReaderFactory +{ + /** + * Private constructor. + * + * <p>This constructor prevents the class from being instantiated.</p> + */ + private XMLReaderFactory () + { + } + + private static final String property = "org.xml.sax.driver"; + + /** + * Attempt to create an XMLReader from system defaults. + * In environments which can support it, the name of the XMLReader + * class is determined by trying each these options in order, and + * using the first one which succeeds:</p> <ul> + * + * <li>If the system property <code>org.xml.sax.driver</code> + * has a value, that is used as an XMLReader class name. </li> + * + * <li>The JAR "Services API" is used to look for a class name + * in the <em>META-INF/services/org.xml.sax.driver</em> file in + * jarfiles available to the runtime.</li> + * + * <li> SAX parser distributions are strongly encouraged to provide + * a default XMLReader class name that will take effect only when + * previous options (on this list) are not successful.</li> + * + * <li>Finally, if {@link ParserFactory#makeParser()} can + * return a system default SAX1 parser, that parser is wrapped in + * a {@link ParserAdapter}. (This is a migration aid for SAX1 + * environments, where the <code>org.xml.sax.parser</code> system + * property will often be usable.) </li> + * + * </ul> + * + * <p> In environments such as small embedded systems, which can not + * support that flexibility, other mechanisms to determine the default + * may be used. </p> + * + * <p>Note that many Java environments allow system properties to be + * initialized on a command line. This means that <em>in most cases</em> + * setting a good value for that property ensures that calls to this + * method will succeed, except when security policies intervene. + * This will also maximize application portability to older SAX + * environments, with less robust implementations of this method. + * </p> + * + * @return A new XMLReader. + * @exception org.xml.sax.SAXException If no default XMLReader class + * can be identified and instantiated. + * @see #createXMLReader(java.lang.String) + */ + public static XMLReader createXMLReader () + throws SAXException + { + String className = null; + ClassLoader loader = NewInstance.getClassLoader (); + + // 1. try the JVM-instance-wide system property + try { className = System.getProperty (property); } + catch (RuntimeException e) { /* normally fails for applets */ } + + // 2. if that fails, try META-INF/services/ + if (className == null) { + try { + String service = "META-INF/services/" + property; + InputStream in; + BufferedReader reader; + + if (loader == null) + in = ClassLoader.getSystemResourceAsStream (service); + else + in = loader.getResourceAsStream (service); + + if (in != null) { + // BEGIN android-modified + reader = new BufferedReader ( + new InputStreamReader (in, "UTF8"), 8192); + // END android-modified + className = reader.readLine (); + in.close (); + } + } catch (Exception e) { + } + } + + // 3. Distro-specific fallback + if (className == null) { +// BEGIN DISTRIBUTION-SPECIFIC + + // EXAMPLE: + // className = "com.example.sax.XmlReader"; + // or a $JAVA_HOME/jre/lib/*properties setting... + +// END DISTRIBUTION-SPECIFIC + } + + // do we know the XMLReader implementation class yet? + if (className != null) + return loadClass (loader, className); + + // 4. panic -- adapt any SAX1 parser + try { + return new ParserAdapter (ParserFactory.makeParser ()); + } catch (Exception e) { + throw new SAXException ("Can't create default XMLReader; " + + "is system property org.xml.sax.driver set?"); + } + } + + + /** + * Attempt to create an XML reader from a class name. + * + * <p>Given a class name, this method attempts to load + * and instantiate the class as an XML reader.</p> + * + * @param className the name of the class that should be instantiated. + * + * <p>Note that this method will not be usable in environments where + * the caller (perhaps an applet) is not permitted to load classes + * dynamically.</p> + * + * @return A new XML reader. + * @exception org.xml.sax.SAXException If the class cannot be + * loaded, instantiated, and cast to XMLReader. + * @see #createXMLReader() + */ + public static XMLReader createXMLReader (String className) + throws SAXException + { + return loadClass (NewInstance.getClassLoader (), className); + } + + private static XMLReader loadClass (ClassLoader loader, String className) + throws SAXException + { + try { + return (XMLReader) NewInstance.newInstance (loader, className); + } catch (ClassNotFoundException e1) { + throw new SAXException("SAX2 driver class " + className + + " not found", e1); + } catch (IllegalAccessException e2) { + throw new SAXException("SAX2 driver class " + className + + " found but cannot be loaded", e2); + } catch (InstantiationException e3) { + throw new SAXException("SAX2 driver class " + className + + " loaded but cannot be instantiated (no empty public constructor?)", + e3); + } catch (ClassCastException e4) { + throw new SAXException("SAX2 driver class " + className + + " does not implement XMLReader", e4); + } + } +} diff --git a/xml/src/main/java/org/xml/sax/helpers/package.html b/xml/src/main/java/org/xml/sax/helpers/package.html new file mode 100644 index 0000000..3a265fd --- /dev/null +++ b/xml/src/main/java/org/xml/sax/helpers/package.html @@ -0,0 +1,13 @@ +<HTML><HEAD> +<!-- $Id: package.html,v 1.6 2002/01/30 20:52:39 dbrownell Exp $ --> +</HEAD><BODY> + +<p>This package contains "helper" classes, including +support for bootstrapping SAX-based applications. + +<p>See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> +for more information about SAX.</p> + +@since Android 1.0 + +</BODY></HTML> diff --git a/xml/src/main/java/org/xml/sax/package.html b/xml/src/main/java/org/xml/sax/package.html new file mode 100644 index 0000000..fbe7108 --- /dev/null +++ b/xml/src/main/java/org/xml/sax/package.html @@ -0,0 +1,299 @@ +<html><head> +<!-- $Id: package.html,v 1.18 2004/04/21 13:06:01 dmegginson Exp $ --> +</head><body> + +<p> This package provides the core SAX APIs. +Some SAX1 APIs are deprecated to encourage integration of +namespace-awareness into designs of new applications +and into maintenance of existing infrastructure. </p> + +<p>See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> +for more information about SAX.</p> + + +<h2> SAX2 Standard Feature Flags </h2> + +<p> One of the essential characteristics of SAX2 is that it added +feature flags which can be used to examine and perhaps modify +parser modes, in particular modes such as validation. +Since features are identified by (absolute) URIs, anyone +can define such features. +Currently defined standard feature URIs have the prefix +<code>http://xml.org/sax/features/</code> before an identifier such as +<code>validation</code>. Turn features on or off using +<em>setFeature</em>. Those standard identifiers are: </p> + + +<table border="1" cellpadding="3" cellspacing="0" width="100%"> + <tr align="center" bgcolor="#ccccff"> + <th>Feature ID</th> + <th>Access</th> + <th>Default</th> + <th>Description</th> + </tr> + + <tr> + <td>external-general-entities</td> + <td><em>read/write</em></td> + <td><em>unspecified</em></td> + <td> Reports whether this parser processes external + general entities; always true if validating. + </td> + </tr> + + <tr> + <td>external-parameter-entities</td> + <td><em>read/write</em></td> + <td><em>unspecified</em></td> + <td> Reports whether this parser processes external + parameter entities; always true if validating. + </td> + </tr> + + <tr> + <td>is-standalone</td> + <td>(parsing) <em>read-only</em>, (not parsing) <em>none</em></td> + <td>not applicable</td> + <td> May be examined only during a parse, after the + <em>startDocument()</em> callback has been completed; read-only. + The value is true if the document specified standalone="yes" in + its XML declaration, and otherwise is false. + </td> + </tr> + + <tr> + <td>lexical-handler/parameter-entities</td> + <td><em>read/write</em></td> + <td><em>unspecified</em></td> + <td> A value of "true" indicates that the LexicalHandler will report + the beginning and end of parameter entities. + </td> + </tr> + + <tr> + <td>namespaces</td> + <td><em>read/write</em></td> + <td>true</td> + <td> A value of "true" indicates namespace URIs and unprefixed local names + for element and attribute names will be available. + </td> + </tr> + + <tr> + <td>namespace-prefixes</td> + <td><em>read/write</em></td> + <td>false</td> + <td> A value of "true" indicates that XML qualified names (with prefixes) and + attributes (including <em>xmlns*</em> attributes) will be available. + </td> + </tr> + + <tr> + <td>resolve-dtd-uris</td> + <td><em>read/write</em></td> + <td><em>true</em></td> + <td> A value of "true" indicates that system IDs in declarations will + be absolutized (relative to their base URIs) before reporting. + (That is the default behavior for all SAX2 XML parsers.) + A value of "false" indicates those IDs will not be absolutized; + parsers will provide the base URI from + <em>Locator.getSystemId()</em>. + This applies to system IDs passed in <ul> + <li><em>DTDHandler.notationDecl()</em>, + <li><em>DTDHandler.unparsedEntityDecl()</em>, and + <li><em>DeclHandler.externalEntityDecl()</em>. + </ul> + It does not apply to <em>EntityResolver.resolveEntity()</em>, + which is not used to report declarations, or to + <em>LexicalHandler.startDTD()</em>, which already provides + the non-absolutized URI. + </td> + </tr> + + <tr> + <td>string-interning</td> + <td><em>read/write</em></td> + <td><em>unspecified</em></td> + <td> Has a value of "true" if all XML names (for elements, prefixes, + attributes, entities, notations, and local names), + as well as Namespace URIs, will have been interned + using <em>java.lang.String.intern</em>. This supports fast + testing of equality/inequality against string constants, + rather than forcing slower calls to <em>String.equals()</em>. + </td> + </tr> + + <tr> + <td>unicode-normalization-checking</td> + <td><em>read/write</em></td> + <td><em>false</em></td> + <td> Controls whether the parser reports Unicode normalization + errors as described in section 2.13 and Appendix B of the + XML 1.1 Recommendation. If true, Unicode normalization + errors are reported using the ErrorHandler.error() callback. + Such errors are not fatal in themselves (though, obviously, + other Unicode-related encoding errors may be). + </td> + </tr> + + <tr> + <td>use-attributes2</td> + <td><em>read-only</em></td> + <td>not applicable</td> + <td> Returns "true" if the <em>Attributes</em> objects passed by + this parser in <em>ContentHandler.startElement()</em> + implement the <a href="ext/Attributes2.html" + ><em>org.xml.sax.ext.Attributes2</em></a> interface. + That interface exposes additional DTD-related information, + such as whether the attribute was specified in the + source text rather than defaulted. + </td> + </tr> + + <tr> + <td>use-locator2</td> + <td><em>read-only</em></td> + <td>not applicable</td> + <td> Returns "true" if the <em>Locator</em> objects passed by + this parser in <em>ContentHandler.setDocumentLocator()</em> + implement the <a href="ext/Locator2.html" + ><em>org.xml.sax.ext.Locator2</em></a> interface. + That interface exposes additional entity information, + such as the character encoding and XML version used. + </td> + </tr> + + <tr> + <td>use-entity-resolver2</td> + <td><em>read/write</em></td> + <td><em>true</em></td> + <td> Returns "true" if, when <em>setEntityResolver</em> is given + an object implementing the <a href="ext/EntityResolver2.html" + ><em>org.xml.sax.ext.EntityResolver2</em></a> interface, + those new methods will be used. + Returns "false" to indicate that those methods will not be used. + </td> + </tr> + + <tr> + <td>validation</td> + <td><em>read/write</em></td> + <td><em>unspecified</em></td> + <td> Controls whether the parser is reporting all validity + errors; if true, all external entities will be read. + </td> + </tr> + + <tr> + <td>xmlns-uris</td> + <td><em>read/write</em></td> + <td><em>false</em></td> + <td> Controls whether, when the <em>namespace-prefixes</em> feature + is set, the parser treats namespace declaration attributes as + being in the <em>http://www.w3.org/2000/xmlns/</em> namespace. + By default, SAX2 conforms to the original "Namespaces in XML" + Recommendation, which explicitly states that such attributes are + not in any namespace. + Setting this optional flag to "true" makes the SAX2 events conform to + a later backwards-incompatible revision of that recommendation, + placing those attributes in a namespace. + </td> + </tr> + + <tr> + <td>xml-1.1</td> + <td><em>read-only</em></td> + <td>not applicable</td> + <td> Returns "true" if the parser supports both XML 1.1 and XML 1.0. + Returns "false" if the parser supports only XML 1.0. + </td> + </tr> + +</table> + +<p> Support for the default values of the +<em>namespaces</em> and <em>namespace-prefixes</em> +properties is required. +Support for any other feature flags is entirely optional. +</p> + +<p> For default values not specified by SAX2, +each XMLReader implementation specifies its default, +or may choose not to expose the feature flag. +Unless otherwise specified here, +implementations may support changing current values +of these standard feature flags, but not while parsing. +</p> + +<h2> SAX2 Standard Handler and Property IDs </h2> + +<p> For parser interface characteristics that are described +as objects, a separate namespace is defined. The +objects in this namespace are again identified by URI, and +the standard property URIs have the prefix +<code>http://xml.org/sax/properties/</code> before an identifier such as +<code>lexical-handler</code> or +<code>dom-node</code>. Manage those properties using +<em>setProperty()</em>. Those identifiers are: </p> + +<table border="1" cellpadding="3" cellspacing="0" width="100%"> + <tr align="center" bgcolor="#ccccff"> + <th>Property ID</th> + <th>Description</th> + </tr> + + <tr> + <td>declaration-handler</td> + <td> Used to see most DTD declarations except those treated + as lexical ("document element name is ...") or which are + mandatory for all SAX parsers (<em>DTDHandler</em>). + The Object must implement <a href="ext/DeclHandler.html" + ><em>org.xml.sax.ext.DeclHandler</em></a>. + </td> + </tr> + + <tr> + <td>document-xml-version</td> + <td> May be examined only during a parse, after the startDocument() + callback has been completed; read-only. This property is a + literal string describing the actual XML version of the document, + such as "1.0" or "1.1". + </td> + </tr> + + <tr> + <td>dom-node</td> + <td> For "DOM Walker" style parsers, which ignore their + <em>parser.parse()</em> parameters, this is used to + specify the DOM (sub)tree being walked by the parser. + The Object must implement the + <em>org.w3c.dom.Node</em> interface. + </td> + </tr> + + <tr> + <td>lexical-handler</td> + <td> Used to see some syntax events that are essential in some + applications: comments, CDATA delimiters, selected general + entity inclusions, and the start and end of the DTD + (and declaration of document element name). + The Object must implement <a href="ext/LexicalHandler.html" + ><em>org.xml.sax.ext.LexicalHandler</em></a>. + </td> + </tr> + + <tr> + <td>xml-string</td> + <td> Readable only during a parser callback, this exposes a <b>TBS</b> + chunk of characters responsible for the current event. </td> + </tr> + +</table> + +<p> All of these standard properties are optional; +XMLReader implementations need not support them. +</p> + +@since Android 1.0 + +</body></html>
\ No newline at end of file diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java new file mode 100644 index 0000000..2c2946f --- /dev/null +++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java @@ -0,0 +1,1116 @@ +/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ +// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) + +package org.xmlpull.v1; + +import java.io.InputStream; +import java.io.IOException; +import java.io.Reader; + +/** + * XML Pull Parser is an interface that defines parsing functionlity provided + * in <a href="http://www.xmlpull.org/">XMLPULL V1 API</a> (visit this website to + * learn more about API and its implementations). + * + * <p>There are following different + * kinds of parser depending on which features are set:<ul> + * <li><b>non-validating</b> parser as defined in XML 1.0 spec when + * FEATURE_PROCESS_DOCDECL is set to true + * <li><b>validating parser</b> as defined in XML 1.0 spec when + * FEATURE_VALIDATION is true (and that implies that FEATURE_PROCESS_DOCDECL is true) + * <li>when FEATURE_PROCESS_DOCDECL is false (this is default and + * if different value is required necessary must be changed before parsing is started) + * then parser behaves like XML 1.0 compliant non-validating parser under condition that + * <em>no DOCDECL is present</em> in XML documents + * (internal entites can still be defined with defineEntityReplacementText()). + * This mode of operation is intened <b>for operation in constrained environments</b> such as J2ME. + * </ul> + * + * + * <p>There are two key methods: next() and nextToken(). While next() provides + * access to high level parsing events, nextToken() allows access to lower + * level tokens. + * + * <p>The current event state of the parser + * can be determined by calling the + * <a href="#getEventType()">getEventType()</a> method. + * Initially, the parser is in the <a href="#START_DOCUMENT">START_DOCUMENT</a> + * state. + * + * <p>The method <a href="#next()">next()</a> advances the parser to the + * next event. The int value returned from next determines the current parser + * state and is identical to the value returned from following calls to + * getEventType (). + * + * <p>Th following event types are seen by next()<dl> + * <dt><a href="#START_TAG">START_TAG</a><dd> An XML start tag was read. + * <dt><a href="#TEXT">TEXT</a><dd> Text content was read; + * the text content can be retreived using the getText() method. + * (when in validating mode next() will not report ignorable whitespaces, use nextToken() instead) + * <dt><a href="#END_TAG">END_TAG</a><dd> An end tag was read + * <dt><a href="#END_DOCUMENT">END_DOCUMENT</a><dd> No more events are available + * </dl> + * + * <p>after first next() or nextToken() (or any other next*() method) + * is called user application can obtain + * XML version, standalone and encoding from XML declaration + * in following ways:<ul> + * <li><b>version</b>: + * getProperty("<a href="http://xmlpull.org/v1/doc/properties.html#xmldecl-version">http://xmlpull.org/v1/doc/properties.html#xmldecl-version</a>") + * returns String ("1.0") or null if XMLDecl was not read or if property is not supported + * <li><b>standalone</b>: + * getProperty("<a href="http://xmlpull.org/v1/doc/features.html#xmldecl-standalone">http://xmlpull.org/v1/doc/features.html#xmldecl-standalone</a>") + * returns Boolean: null if there was no standalone declaration + * or if property is not supported + * otherwise returns Boolean(true) if standalon="yes" and Boolean(false) when standalone="no" + * <li><b>encoding</b>: obtained from getInputEncoding() + * null if stream had unknown encoding (not set in setInputStream) + * and it was not declared in XMLDecl + * </ul> + * + * A minimal example for using this API may look as follows: + * <pre> + * import java.io.IOException; + * import java.io.StringReader; + * + * import org.xmlpull.v1.XmlPullParser; + * import org.xmlpull.v1.<a href="XmlPullParserException.html">XmlPullParserException.html</a>; + * import org.xmlpull.v1.<a href="XmlPullParserFactory.html">XmlPullParserFactory</a>; + * + * public class SimpleXmlPullApp + * { + * + * public static void main (String args[]) + * throws XmlPullParserException, IOException + * { + * XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + * factory.setNamespaceAware(true); + * XmlPullParser xpp = factory.newPullParser(); + * + * xpp.<a href="#setInput">setInput</a>( new StringReader ( "<foo>Hello World!</foo>" ) ); + * int eventType = xpp.getEventType(); + * while (eventType != XmlPullParser.END_DOCUMENT) { + * if(eventType == XmlPullParser.START_DOCUMENT) { + * System.out.println("Start document"); + * } else if(eventType == XmlPullParser.END_DOCUMENT) { + * System.out.println("End document"); + * } else if(eventType == XmlPullParser.START_TAG) { + * System.out.println("Start tag "+xpp.<a href="#getName()">getName()</a>); + * } else if(eventType == XmlPullParser.END_TAG) { + * System.out.println("End tag "+xpp.getName()); + * } else if(eventType == XmlPullParser.TEXT) { + * System.out.println("Text "+xpp.<a href="#getText()">getText()</a>); + * } + * eventType = xpp.next(); + * } + * } + * } + * </pre> + * + * <p>The above example will generate the following output: + * <pre> + * Start document + * Start tag foo + * Text Hello World! + * End tag foo + * </pre> + * + * <p>For more details on API usage, please refer to the + * quick Introduction available at <a href="http://www.xmlpull.org">http://www.xmlpull.org</a> + * + * @see XmlPullParserFactory + * @see #defineEntityReplacementText + * @see #getName + * @see #getNamespace + * @see #getText + * @see #next + * @see #nextToken + * @see #setInput + * @see #FEATURE_PROCESS_DOCDECL + * @see #FEATURE_VALIDATION + * @see #START_DOCUMENT + * @see #START_TAG + * @see #TEXT + * @see #END_TAG + * @see #END_DOCUMENT + * + * @author <a href="http://www-ai.cs.uni-dortmund.de/PERSONAL/haustein.html">Stefan Haustein</a> + * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a> + */ + +public interface XmlPullParser { + + /** This constant represents the default namespace (empty string "") */ + String NO_NAMESPACE = ""; + + // ---------------------------------------------------------------------------- + // EVENT TYPES as reported by next() + + /** + * Signalize that parser is at the very beginning of the document + * and nothing was read yet. + * This event type can only be observed by calling getEvent() + * before the first call to next(), nextToken, or nextTag()</a>). + * + * @see #next + * @see #nextToken + */ + int START_DOCUMENT = 0; + + /** + * Logical end of the xml document. Returned from getEventType, next() + * and nextToken() + * when the end of the input document has been reached. + * <p><strong>NOTE:</strong> calling again + * <a href="#next()">next()</a> or <a href="#nextToken()">nextToken()</a> + * will result in exception being thrown. + * + * @see #next + * @see #nextToken + */ + int END_DOCUMENT = 1; + + /** + * Returned from getEventType(), + * <a href="#next()">next()</a>, <a href="#nextToken()">nextToken()</a> when + * a start tag was read. + * The name of start tag is available from getName(), its namespace and prefix are + * available from getNamespace() and getPrefix() + * if <a href='#FEATURE_PROCESS_NAMESPACES'>namespaces are enabled</a>. + * See getAttribute* methods to retrieve element attributes. + * See getNamespace* methods to retrieve newly declared namespaces. + * + * @see #next + * @see #nextToken + * @see #getName + * @see #getPrefix + * @see #getNamespace + * @see #getAttributeCount + * @see #getDepth + * @see #getNamespaceCount + * @see #getNamespace + * @see #FEATURE_PROCESS_NAMESPACES + */ + int START_TAG = 2; + + /** + * Returned from getEventType(), <a href="#next()">next()</a>, or + * <a href="#nextToken()">nextToken()</a> when an end tag was read. + * The name of start tag is available from getName(), its + * namespace and prefix are + * available from getNamespace() and getPrefix(). + * + * @see #next + * @see #nextToken + * @see #getName + * @see #getPrefix + * @see #getNamespace + * @see #FEATURE_PROCESS_NAMESPACES + */ + int END_TAG = 3; + + + /** + * Character data was read and will is available by calling getText(). + * <p><strong>Please note:</strong> <a href="#next()">next()</a> will + * accumulate multiple + * events into one TEXT event, skipping IGNORABLE_WHITESPACE, + * PROCESSING_INSTRUCTION and COMMENT events, + * In contrast, <a href="#nextToken()">nextToken()</a> will stop reading + * text when any other event is observed. + * Also, when the state was reached by calling next(), the text value will + * be normalized, whereas getText() will + * return unnormalized content in the case of nextToken(). This allows + * an exact roundtrip without chnanging line ends when examining low + * level events, whereas for high level applications the text is + * normalized apropriately. + * + * @see #next + * @see #nextToken + * @see #getText + */ + int TEXT = 4; + + // ---------------------------------------------------------------------------- + // additional events exposed by lower level nextToken() + + /** + * A CDATA sections was just read; + * this token is available only from calls to <a href="#nextToken()">nextToken()</a>. + * A call to next() will accumulate various text events into a single event + * of type TEXT. The text contained in the CDATA section is available + * by callling getText(). + * + * @see #nextToken + * @see #getText + */ + int CDSECT = 5; + + /** + * An entity reference was just read; + * this token is available from <a href="#nextToken()">nextToken()</a> + * only. The entity name is available by calling getName(). If available, + * the replacement text can be obtained by calling getTextt(); otherwise, + * the user is responsibile for resolving the entity reference. + * This event type is never returned from next(); next() will + * accumulate the replacement text and other text + * events to a single TEXT event. + * + * @see #nextToken + * @see #getText + */ + int ENTITY_REF = 6; + + /** + * Ignorable whitespace was just read. + * This token is available only from <a href="#nextToken()">nextToken()</a>). + * For non-validating + * parsers, this event is only reported by nextToken() when outside + * the root element. + * Validating parsers may be able to detect ignorable whitespace at + * other locations. + * The ignorable whitespace string is available by calling getText() + * + * <p><strong>NOTE:</strong> this is different from calling the + * isWhitespace() method, since text content + * may be whitespace but not ignorable. + * + * Ignorable whitespace is skipped by next() automatically; this event + * type is never returned from next(). + * + * @see #nextToken + * @see #getText + */ + int IGNORABLE_WHITESPACE = 7; + + /** + * An XML processing instruction declaration was just read. This + * event type is available only via <a href="#nextToken()">nextToken()</a>. + * getText() will return text that is inside the processing instruction. + * Calls to next() will skip processing instructions automatically. + * @see #nextToken + * @see #getText + */ + int PROCESSING_INSTRUCTION = 8; + + /** + * An XML comment was just read. This event type is this token is + * available via <a href="#nextToken()">nextToken()</a> only; + * calls to next() will skip comments automatically. + * The content of the comment can be accessed using the getText() + * method. + * + * @see #nextToken + * @see #getText + */ + int COMMENT = 9; + + /** + * An XML document type declaration was just read. This token is + * available from <a href="#nextToken()">nextToken()</a> only. + * The unparsed text inside the doctype is available via + * the getText() method. + * + * @see #nextToken + * @see #getText + */ + int DOCDECL = 10; + + /** + * This array can be used to convert the event type integer constants + * such as START_TAG or TEXT to + * to a string. For example, the value of TYPES[START_TAG] is + * the string "START_TAG". + * + * This array is intended for diagnostic output only. Relying + * on the contents of the array may be dangerous since malicous + * applications may alter the array, although it is final, due + * to limitations of the Java language. + */ + String [] TYPES = { + "START_DOCUMENT", + "END_DOCUMENT", + "START_TAG", + "END_TAG", + "TEXT", + "CDSECT", + "ENTITY_REF", + "IGNORABLE_WHITESPACE", + "PROCESSING_INSTRUCTION", + "COMMENT", + "DOCDECL" + }; + + + // ---------------------------------------------------------------------------- + // namespace related features + + /** + * This feature determines whether the parser processes + * namespaces. As for all features, the default value is false. + * <p><strong>NOTE:</strong> The value can not be changed during + * parsing an must be set before parsing. + * + * @see #getFeature + * @see #setFeature + */ + String FEATURE_PROCESS_NAMESPACES = + "http://xmlpull.org/v1/doc/features.html#process-namespaces"; + + /** + * This feature determines whether namespace attributes are + * exposed via the attribute access methods. Like all features, + * the default value is false. This feature cannot be changed + * during parsing. + * + * @see #getFeature + * @see #setFeature + */ + String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = + "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes"; + + /** + * This feature determines whether the document declaration + * is processed. If set to false, + * the DOCDECL event type is reported by nextToken() + * and ignored by next(). + * + * If this featue is activated, then the document declaration + * must be processed by the parser. + * + * <p><strong>Please note:</strong> If the document type declaration + * was ignored, entity references may cause exceptions + * later in the parsing process. + * The default value of this feature is false. It cannot be changed + * during parsing. + * + * @see #getFeature + * @see #setFeature + */ + String FEATURE_PROCESS_DOCDECL = + "http://xmlpull.org/v1/doc/features.html#process-docdecl"; + + /** + * If this feature is activated, all validation errors as + * defined in the XML 1.0 sepcification are reported. + * This implies that FEATURE_PROCESS_DOCDECL is true and both, the + * internal and external document type declaration will be processed. + * <p><strong>Please Note:</strong> This feature can not be changed + * during parsing. The default value is false. + * + * @see #getFeature + * @see #setFeature + */ + String FEATURE_VALIDATION = + "http://xmlpull.org/v1/doc/features.html#validation"; + + /** + * Use this call to change the general behaviour of the parser, + * such as namespace processing or doctype declaration handling. + * This method must be called before the first call to next or + * nextToken. Otherwise, an exception is thrown. + * <p>Example: call setFeature(FEATURE_PROCESS_NAMESPACES, true) in order + * to switch on namespace processing. The initial settings correspond + * to the properties requested from the XML Pull Parser factory. + * If none were requested, all feautures are deactivated by default. + * + * @exception XmlPullParserException If the feature is not supported or can not be set + * @exception IllegalArgumentException If string with the feature name is null + */ + void setFeature(String name, + boolean state) throws XmlPullParserException; + + /** + * Returns the current value of the given feature. + * <p><strong>Please note:</strong> unknown features are + * <strong>always</strong> returned as false. + * + * @param name The name of feature to be retrieved. + * @return The value of the feature. + * @exception IllegalArgumentException if string the feature name is null + */ + + boolean getFeature(String name); + + /** + * Set the value of a property. + * + * The property name is any fully-qualified URI. + * + * @exception XmlPullParserException If the property is not supported or can not be set + * @exception IllegalArgumentException If string with the property name is null + */ + void setProperty(String name, + Object value) throws XmlPullParserException; + + /** + * Look up the value of a property. + * + * The property name is any fully-qualified URI. + * <p><strong>NOTE:</strong> unknown properties are <strong>always</strong> + * returned as null. + * + * @param name The name of property to be retrieved. + * @return The value of named property. + */ + Object getProperty(String name); + + + /** + * Set the input source for parser to the given reader and + * resets the parser. The event type is set to the initial value + * START_DOCUMENT. + * Setting the reader to null will just stop parsing and + * reset parser state, + * allowing the parser to free internal resources + * such as parsing buffers. + */ + void setInput(Reader in) throws XmlPullParserException; + + + /** + * Sets the input stream the parser is going to process. + * This call resets the parser state and sets the event type + * to the initial value START_DOCUMENT. + * + * <p><strong>NOTE:</strong> If an input encoding string is passed, + * it MUST be used. Otherwise, + * if inputEncoding is null, the parser SHOULD try to determine + * input encoding following XML 1.0 specification (see below). + * If encoding detection is supported then following feature + * <a href="http://xmlpull.org/v1/doc/features.html#detect-encoding">http://xmlpull.org/v1/doc/features.html#detect-encoding</a> + * MUST be true amd otherwise it must be false + * + * @param inputStream contains a raw byte input stream of possibly + * unknown encoding (when inputEncoding is null). + * + * @param inputEncoding if not null it MUST be used as encoding for inputStream + */ + void setInput(InputStream inputStream, String inputEncoding) + throws XmlPullParserException; + + /** + * Returns the input encoding if known, null otherwise. + * If setInput(InputStream, inputEncoding) was called with an inputEncoding + * value other than null, this value must be returned + * from this method. Otherwise, if inputEncoding is null and + * the parser suppports the encoding detection feature + * (http://xmlpull.org/v1/doc/features.html#detect-encoding), + * it must return the detected encoding. + * If setInput(Reader) was called, null is returned. + * After first call to next if XML declaration was present this method + * will return encoding declared. + */ + String getInputEncoding(); + + /** + * Set new value for entity replacement text as defined in + * <a href="http://www.w3.org/TR/REC-xml#intern-replacement">XML 1.0 Section 4.5 + * Construction of Internal Entity Replacement Text</a>. + * If FEATURE_PROCESS_DOCDECL or FEATURE_VALIDATION are set, calling this + * function will result in an exception -- when processing of DOCDECL is + * enabled, there is no need to the entity replacement text manually. + * + * <p>The motivation for this function is to allow very small + * implementations of XMLPULL that will work in J2ME environments. + * Though these implementations may not be able to process the document type + * declaration, they still can work with known DTDs by using this function. + * + * <p><b>Please notes:</b> The given value is used literally as replacement text + * and it corresponds to declaring entity in DTD that has all special characters + * escaped: left angle bracket is replaced with &lt;, ampersnad with &amp; + * and so on. + * + * <p><b>Note:</b> The given value is the literal replacement text and must not + * contain any other entity reference (if it contains any entity reference + * there will be no further replacement). + * + * <p><b>Note:</b> The list of pre-defined entity names will + * always contain standard XML entities such as + * amp (&amp;), lt (&lt;), gt (&gt;), quot (&quot;), and apos (&apos;). + * Those cannot be redefined by this method! + * + * @see #setInput + * @see #FEATURE_PROCESS_DOCDECL + * @see #FEATURE_VALIDATION + */ + void defineEntityReplacementText( String entityName, + String replacementText ) throws XmlPullParserException; + + /** + * Returns the numbers of elements in the namespace stack for the given + * depth. + * If namespaces are not enabled, 0 is returned. + * + * <p><b>NOTE:</b> when parser is on END_TAG then it is allowed to call + * this function with getDepth()+1 argument to retrieve position of namespace + * prefixes and URIs that were declared on corresponding START_TAG. + * <p><b>NOTE:</b> to retrieve lsit of namespaces declared in current element:<pre> + * XmlPullParser pp = ... + * int nsStart = pp.getNamespaceCount(pp.getDepth()-1); + * int nsEnd = pp.getNamespaceCount(pp.getDepth()); + * for (int i = nsStart; i < nsEnd; i++) { + * String prefix = pp.getNamespacePrefix(i); + * String ns = pp.getNamespaceUri(i); + * // ... + * } + * </pre> + * + * @see #getNamespacePrefix + * @see #getNamespaceUri + * @see #getNamespace() + * @see #getNamespace(String) + */ + int getNamespaceCount(int depth) throws XmlPullParserException; + + /** + * Returns the namespace prefixe for the given position + * in the namespace stack. + * Default namespace declaration (xmlns='...') will have null as prefix. + * If the given index is out of range, an exception is thrown. + * <p><b>Please note:</b> when the parser is on an END_TAG, + * namespace prefixes that were declared + * in the corresponding START_TAG are still accessible + * although they are no longer in scope. + */ + String getNamespacePrefix(int pos) throws XmlPullParserException; + + /** + * Returns the namespace URI for the given position in the + * namespace stack + * If the position is out of range, an exception is thrown. + * <p><b>NOTE:</b> when parser is on END_TAG then namespace prefixes that were declared + * in corresponding START_TAG are still accessible even though they are not in scope + */ + String getNamespaceUri(int pos) throws XmlPullParserException; + + /** + * Returns the URI corresponding to the given prefix, + * depending on current state of the parser. + * + * <p>If the prefix was not declared in the current scope, + * null is returned. The default namespace is included + * in the namespace table and is available via + * getNamespace (null). + * + * <p>This method is a convenience method for + * + * <pre> + * for (int i = getNamespaceCount(getDepth ())-1; i >= 0; i--) { + * if (getNamespacePrefix(i).equals( prefix )) { + * return getNamespaceUri(i); + * } + * } + * return null; + * </pre> + * + * <p><strong>Please note:</strong> parser implementations + * may provide more efifcient lookup, e.g. using a Hashtable. + * The 'xml' prefix is bound to "http://www.w3.org/XML/1998/namespace", as + * defined in the + * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a> + * specification. Analogous, the 'xmlns' prefix is resolved to + * <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a> + * + * @see #getNamespaceCount + * @see #getNamespacePrefix + * @see #getNamespaceUri + */ + String getNamespace (String prefix); + + + // -------------------------------------------------------------------------- + // miscellaneous reporting methods + + /** + * Returns the current depth of the element. + * Outside the root element, the depth is 0. The + * depth is incremented by 1 when a start tag is reached. + * The depth is decremented AFTER the end tag + * event was observed. + * + * <pre> + * <!-- outside --> 0 + * <root> 1 + * sometext 1 + * <foobar> 2 + * </foobar> 2 + * </root> 1 + * <!-- outside --> 0 + * </pre> + */ + int getDepth(); + + /** + * Returns a short text describing the current parser state, including + * the position, a + * description of the current event and the data source if known. + * This method is especially useful to provide meaningful + * error messages and for debugging purposes. + */ + String getPositionDescription (); + + + /** + * Returns the current line number, starting from 1. + * When the parser does not know the current line number + * or can not determine it, -1 is returned (e.g. for WBXML). + * + * @return current line number or -1 if unknown. + */ + int getLineNumber(); + + /** + * Returns the current column number, starting from 0. + * When the parser does not know the current column number + * or can not determine it, -1 is returned (e.g. for WBXML). + * + * @return current column number or -1 if unknown. + */ + int getColumnNumber(); + + + // -------------------------------------------------------------------------- + // TEXT related methods + + /** + * Checks whether the current TEXT event contains only whitespace + * characters. + * For IGNORABLE_WHITESPACE, this is always true. + * For TEXT and CDSECT, false is returned when the current event text + * contains at least one non-white space character. For any other + * event type an exception is thrown. + * + * <p><b>Please note:</b> non-validating parsers are not + * able to distinguish whitespace and ignorable whitespace, + * except from whitespace outside the root element. Ignorable + * whitespace is reported as separate event, which is exposed + * via nextToken only. + * + */ + boolean isWhitespace() throws XmlPullParserException; + + /** + * Returns the text content of the current event as String. + * The value returned depends on current event type, + * for example for TEXT event it is element content + * (this is typical case when next() is used). + * + * See description of nextToken() for detailed description of + * possible returned values for different types of events. + * + * <p><strong>NOTE:</strong> in case of ENTITY_REF, this method returns + * the entity replacement text (or null if not available). This is + * the only case where + * getText() and getTextCharacters() return different values. + * + * @see #getEventType + * @see #next + * @see #nextToken + */ + String getText (); + + + /** + * Returns the buffer that contains the text of the current event, + * as well as the start offset and length relevant for the current + * event. See getText(), next() and nextToken() for description of possible returned values. + * + * <p><strong>Please note:</strong> this buffer must not + * be modified and its content MAY change after a call to + * next() or nextToken(). This method will always return the + * same value as getText(), except for ENTITY_REF. In the case + * of ENTITY ref, getText() returns the replacement text and + * this method returns the actual input buffer containing the + * entity name. + * If getText() returns null, this method returns null as well and + * the values returned in the holder array MUST be -1 (both start + * and length). + * + * @see #getText + * @see #next + * @see #nextToken + * + * @param holderForStartAndLength Must hold an 2-element int array + * into which the start offset and length values will be written. + * @return char buffer that contains the text of the current event + * (null if the current event has no text associated). + */ + char[] getTextCharacters(int [] holderForStartAndLength); + + // -------------------------------------------------------------------------- + // START_TAG / END_TAG shared methods + + /** + * Returns the namespace URI of the current element. + * The default namespace is represented + * as empty string. + * If namespaces are not enabled, an empty String ("") is always returned. + * The current event must be START_TAG or END_TAG; otherwise, + * null is returned. + */ + String getNamespace (); + + /** + * For START_TAG or END_TAG events, the (local) name of the current + * element is returned when namespaces are enabled. When namespace + * processing is disabled, the raw name is returned. + * For ENTITY_REF events, the entity name is returned. + * If the current event is not START_TAG, END_TAG, or ENTITY_REF, + * null is returned. + * <p><b>Please note:</b> To reconstruct the raw element name + * when namespaces are enabled and the prefix is not null, + * you will need to add the prefix and a colon to localName.. + * + */ + String getName(); + + /** + * Returns the prefix of the current element. + * If the element is in the default namespace (has no prefix), + * null is returned. + * If namespaces are not enabled, or the current event + * is not START_TAG or END_TAG, null is returned. + */ + String getPrefix(); + + /** + * Returns true if the current event is START_TAG and the tag + * is degenerated + * (e.g. <foobar/>). + * <p><b>NOTE:</b> if the parser is not on START_TAG, an exception + * will be thrown. + */ + boolean isEmptyElementTag() throws XmlPullParserException; + + // -------------------------------------------------------------------------- + // START_TAG Attributes retrieval methods + + /** + * Returns the number of attributes of the current start tag, or + * -1 if the current event type is not START_TAG + * + * @see #getAttributeNamespace + * @see #getAttributeName + * @see #getAttributePrefix + * @see #getAttributeValue + */ + int getAttributeCount(); + + /** + * Returns the namespace URI of the attribute + * with the given index (starts from 0). + * Returns an empty string ("") if namespaces are not enabled + * or the attribute has no namespace. + * Throws an IndexOutOfBoundsException if the index is out of range + * or the current event type is not START_TAG. + * + * <p><strong>NOTE:</strong> if FEATURE_REPORT_NAMESPACE_ATTRIBUTES is set + * then namespace attributes (xmlns:ns='...') must be reported + * with namespace + * <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a> + * (visit this URL for description!). + * The default namespace attribute (xmlns="...") will be reported with empty namespace. + * <p><strong>NOTE:</strong>The xml prefix is bound as defined in + * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a> + * specification to "http://www.w3.org/XML/1998/namespace". + * + * @param index zero-based index of attribute + * @return attribute namespace, + * empty string ("") is returned if namesapces processing is not enabled or + * namespaces processing is enabled but attribute has no namespace (it has no prefix). + */ + String getAttributeNamespace (int index); + + /** + * Returns the local name of the specified attribute + * if namespaces are enabled or just attribute name if namespaces are disabled. + * Throws an IndexOutOfBoundsException if the index is out of range + * or current event type is not START_TAG. + * + * @param index zero-based index of attribute + * @return attribute name (null is never returned) + */ + String getAttributeName (int index); + + /** + * Returns the prefix of the specified attribute + * Returns null if the element has no prefix. + * If namespaces are disabled it will always return null. + * Throws an IndexOutOfBoundsException if the index is out of range + * or current event type is not START_TAG. + * + * @param index zero-based index of attribute + * @return attribute prefix or null if namespaces processing is not enabled. + */ + String getAttributePrefix(int index); + + /** + * Returns the type of the specified attribute + * If parser is non-validating it MUST return CDATA. + * + * @param index zero-based index of attribute + * @return attribute type (null is never returned) + */ + String getAttributeType(int index); + + /** + * Returns if the specified attribute was not in input was declared in XML. + * If parser is non-validating it MUST always return false. + * This information is part of XML infoset: + * + * @param index zero-based index of attribute + * @return false if attribute was in input + */ + boolean isAttributeDefault(int index); + + /** + * Returns the given attributes value. + * Throws an IndexOutOfBoundsException if the index is out of range + * or current event type is not START_TAG. + * + * <p><strong>NOTE:</strong> attribute value must be normalized + * (including entity replacement text if PROCESS_DOCDECL is false) as described in + * <a href="http://www.w3.org/TR/REC-xml#AVNormalize">XML 1.0 section + * 3.3.3 Attribute-Value Normalization</a> + * + * @see #defineEntityReplacementText + * + * @param index zero-based index of attribute + * @return value of attribute (null is never returned) + */ + String getAttributeValue(int index); + + /** + * Returns the attributes value identified by namespace URI and namespace localName. + * If namespaces are disabled namespace must be null. + * If current event type is not START_TAG then IndexOutOfBoundsException will be thrown. + * + * <p><strong>NOTE:</strong> attribute value must be normalized + * (including entity replacement text if PROCESS_DOCDECL is false) as described in + * <a href="http://www.w3.org/TR/REC-xml#AVNormalize">XML 1.0 section + * 3.3.3 Attribute-Value Normalization</a> + * + * @see #defineEntityReplacementText + * + * @param namespace Namespace of the attribute if namespaces are enabled otherwise must be null + * @param name If namespaces enabled local name of attribute otherwise just attribute name + * @return value of attribute or null if attribute with given name does not exist + */ + String getAttributeValue(String namespace, + String name); + + // -------------------------------------------------------------------------- + // actual parsing methods + + /** + * Returns the type of the current event (START_TAG, END_TAG, TEXT, etc.) + * + * @see #next() + * @see #nextToken() + */ + int getEventType() + throws XmlPullParserException; + + /** + * Get next parsing event - element content wil be coalesced and only one + * TEXT event must be returned for whole element content + * (comments and processing instructions will be ignored and emtity references + * must be expanded or exception mus be thrown if entity reerence can not be exapnded). + * If element content is empty (content is "") then no TEXT event will be reported. + * + * <p><b>NOTE:</b> empty element (such as <tag/>) will be reported + * with two separate events: START_TAG, END_TAG - it must be so to preserve + * parsing equivalency of empty element to <tag></tag>. + * (see isEmptyElementTag ()) + * + * @see #isEmptyElementTag + * @see #START_TAG + * @see #TEXT + * @see #END_TAG + * @see #END_DOCUMENT + */ + + int next() + throws XmlPullParserException, IOException; + + + /** + * This method works similarly to next() but will expose + * additional event types (COMMENT, CDSECT, DOCDECL, ENTITY_REF, PROCESSING_INSTRUCTION, or + * IGNORABLE_WHITESPACE) if they are available in input. + * + * <p>If special feature + * <a href="http://xmlpull.org/v1/doc/features.html#xml-roundtrip">FEATURE_XML_ROUNDTRIP</a> + * (identified by URI: http://xmlpull.org/v1/doc/features.html#xml-roundtrip) + * is enabled it is possible to do XML document round trip ie. reproduce + * exectly on output the XML input using getText(): + * returned content is always unnormalized (exactly as in input). + * Otherwise returned content is end-of-line normalized as described + * <a href="http://www.w3.org/TR/REC-xml#sec-line-ends">XML 1.0 End-of-Line Handling</a> + * and. Also when this feature is enabled exact content of START_TAG, END_TAG, + * DOCDECL and PROCESSING_INSTRUCTION is available. + * + * <p>Here is the list of tokens that can be returned from nextToken() + * and what getText() and getTextCharacters() returns:<dl> + * <dt>START_DOCUMENT<dd>null + * <dt>END_DOCUMENT<dd>null + * <dt>START_TAG<dd>null unless FEATURE_XML_ROUNDTRIP + * enabled and then returns XML tag, ex: <tag attr='val'> + * <dt>END_TAG<dd>null unless FEATURE_XML_ROUNDTRIP + * id enabled and then returns XML tag, ex: </tag> + * <dt>TEXT<dd>return element content. + * <br>Note: that element content may be delivered in multiple consecutive TEXT events. + * <dt>IGNORABLE_WHITESPACE<dd>return characters that are determined to be ignorable white + * space. If the FEATURE_XML_ROUNDTRIP is enabled all whitespace content outside root + * element will always reported as IGNORABLE_WHITESPACE otherise rteporting is optional. + * <br>Note: that element content may be delevered in multiple consecutive IGNORABLE_WHITESPACE events. + * <dt>CDSECT<dd> + * return text <em>inside</em> CDATA + * (ex. 'fo<o' from <!CDATA[fo<o]]>) + * <dt>PROCESSING_INSTRUCTION<dd> + * if FEATURE_XML_ROUNDTRIP is true + * return exact PI content ex: 'pi foo' from <?pi foo?> + * otherwise it may be exact PI content or concatenation of PI target, + * space and data so for example for + * <?target data?> string "target data" may + * be returned if FEATURE_XML_ROUNDTRIP is false. + * <dt>COMMENT<dd>return comment content ex. 'foo bar' from <!--foo bar--> + * <dt>ENTITY_REF<dd>getText() MUST return entity replacement text if PROCESS_DOCDECL is false + * otherwise getText() MAY return null, + * additionally getTextCharacters() MUST return entity name + * (for example 'entity_name' for &entity_name;). + * <br><b>NOTE:</b> this is the only place where value returned from getText() and + * getTextCharacters() <b>are different</b> + * <br><b>NOTE:</b> it is user responsibility to resolve entity reference + * if PROCESS_DOCDECL is false and there is no entity replacement text set in + * defineEntityReplacementText() method (getText() will be null) + * <br><b>NOTE:</b> character entities (ex. &#32;) and standard entities such as + * &amp; &lt; &gt; &quot; &apos; are reported as well + * and are <b>not</b> reported as TEXT tokens but as ENTITY_REF tokens! + * This requirement is added to allow to do roundtrip of XML documents! + * <dt>DOCDECL<dd> + * if FEATURE_XML_ROUNDTRIP is true or PROCESS_DOCDECL is false + * then return what is inside of DOCDECL for example it returns:<pre> + * " titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd" + * [<!ENTITY % active.links "INCLUDE">]"</pre> + * <p>for input document that contained:<pre> + * <!DOCTYPE titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd" + * [<!ENTITY % active.links "INCLUDE">]></pre> + * otherwise if FEATURE_XML_ROUNDTRIP is false and PROCESS_DOCDECL is true + * then what is returned is undefined (it may be even null) + * </dd> + * </dl> + * + * <p><strong>NOTE:</strong> there is no gurantee that there will only one TEXT or + * IGNORABLE_WHITESPACE event from nextToken() as parser may chose to deliver element content in + * multiple tokens (dividing element content into chunks) + * + * <p><strong>NOTE:</strong> whether returned text of token is end-of-line normalized + * is depending on FEATURE_XML_ROUNDTRIP. + * + * <p><strong>NOTE:</strong> XMLDecl (<?xml ...?>) is not reported but its content + * is available through optional properties (see class description above). + * + * @see #next + * @see #START_TAG + * @see #TEXT + * @see #END_TAG + * @see #END_DOCUMENT + * @see #COMMENT + * @see #DOCDECL + * @see #PROCESSING_INSTRUCTION + * @see #ENTITY_REF + * @see #IGNORABLE_WHITESPACE + */ + int nextToken() + throws XmlPullParserException, IOException; + + //----------------------------------------------------------------------------- + // utility methods to mak XML parsing easier ... + + /** + * Test if the current event is of the given type and if the + * namespace and name do match. null will match any namespace + * and any name. If the test is not passed, an exception is + * thrown. The exception text indicates the parser position, + * the expected event and the current event that is not meeting the + * requirement. + * + * <p>Essentially it does this + * <pre> + * if (type != getEventType() + * || (namespace != null && !namespace.equals( getNamespace () ) ) + * || (name != null && !name.equals( getName() ) ) ) + * throw new XmlPullParserException( "expected "+ TYPES[ type ]+getPositionDescription()); + * </pre> + */ + void require(int type, String namespace, String name) + throws XmlPullParserException, IOException; + + /** + * If current event is START_TAG then if next element is TEXT then element content is returned + * or if next event is END_TAG then empty string is returned, otherwise exception is thrown. + * After calling this function successfully parser will be positioned on END_TAG. + * + * <p>The motivation for this function is to allow to parse consistently both + * empty elements and elements that has non empty content, for example for input: <ol> + * <li><tag>foo</tag> + * <li><tag></tag> (which is equivalent to <tag/> + * both input can be parsed with the same code: + * <pre> + * p.nextTag() + * p.requireEvent(p.START_TAG, "", "tag"); + * String content = p.nextText(); + * p.requireEvent(p.END_TAG, "", "tag"); + * </pre> + * This function together with nextTag make it very easy to parse XML that has + * no mixed content. + * + * + * <p>Essentially it does this + * <pre> + * if(getEventType() != START_TAG) { + * throw new XmlPullParserException( + * "parser must be on START_TAG to read next text", this, null); + * } + * int eventType = next(); + * if(eventType == TEXT) { + * String result = getText(); + * eventType = next(); + * if(eventType != END_TAG) { + * throw new XmlPullParserException( + * "event TEXT it must be immediately followed by END_TAG", this, null); + * } + * return result; + * } else if(eventType == END_TAG) { + * return ""; + * } else { + * throw new XmlPullParserException( + * "parser must be on START_TAG or TEXT to read text", this, null); + * } + * </pre> + */ + String nextText() throws XmlPullParserException, IOException; + + /** + * Call next() and return event if it is START_TAG or END_TAG + * otherwise throw an exception. + * It will skip whitespace TEXT before actual tag if any. + * + * <p>essentially it does this + * <pre> + * int eventType = next(); + * if(eventType == TEXT && isWhitespace()) { // skip whitespace + * eventType = next(); + * } + * if (eventType != START_TAG && eventType != END_TAG) { + * throw new XmlPullParserException("expected start or end tag", this, null); + * } + * return eventType; + * </pre> + */ + int nextTag() throws XmlPullParserException, IOException; + +} + diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParserException.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParserException.java new file mode 100644 index 0000000..b4b4b71 --- /dev/null +++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParserException.java @@ -0,0 +1,76 @@ +/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ +// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) + +package org.xmlpull.v1; + +/** + * This exception is thrown to signal XML Pull Parser related faults. + * + * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a> + */ +public class XmlPullParserException extends Exception { + protected Throwable detail; + protected int row = -1; + protected int column = -1; + + /* public XmlPullParserException() { + }*/ + + public XmlPullParserException(String s) { + super(s); + } + + /* + public XmlPullParserException(String s, Throwable thrwble) { + super(s); + this.detail = thrwble; + } + + public XmlPullParserException(String s, int row, int column) { + super(s); + this.row = row; + this.column = column; + } + */ + + public XmlPullParserException(String msg, XmlPullParser parser, Throwable chain) { + super ((msg == null ? "" : msg+" ") + + (parser == null ? "" : "(position:"+parser.getPositionDescription()+") ") + + (chain == null ? "" : "caused by: "+chain)); + + if (parser != null) { + this.row = parser.getLineNumber(); + this.column = parser.getColumnNumber(); + } + this.detail = chain; + } + + public Throwable getDetail() { return detail; } + // public void setDetail(Throwable cause) { this.detail = cause; } + public int getLineNumber() { return row; } + public int getColumnNumber() { return column; } + + /* + public String getMessage() { + if(detail == null) + return super.getMessage(); + else + return super.getMessage() + "; nested exception is: \n\t" + + detail.getMessage(); + } + */ + + //NOTE: code that prints this and detail is difficult in J2ME + public void printStackTrace() { + if (detail == null) { + super.printStackTrace(); + } else { + synchronized(System.err) { + System.err.println(super.getMessage() + "; nested exception is:"); + detail.printStackTrace(); + } + } + } + +} + diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java new file mode 100644 index 0000000..7b786f6 --- /dev/null +++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java @@ -0,0 +1,349 @@ +/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ +// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) + +package org.xmlpull.v1; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +/** + * This class is used to create implementations of XML Pull Parser defined in XMPULL V1 API. + * The name of actual factory class will be determined based on several parameters. + * It works similar to JAXP but tailored to work in J2ME environments + * (no access to system properties or file system) so name of parser class factory to use + * and its class used for loading (no class loader - on J2ME no access to context class loaders) + * must be passed explicitly. If no name of parser factory was passed (or is null) + * it will try to find name by searching in CLASSPATH for + * META-INF/services/org.xmlpull.v1.XmlPullParserFactory resource that should contain + * a comma separated list of class names of factories or parsers to try (in order from + * left to the right). If none found, it will throw an exception. + * + * <br /><strong>NOTE:</strong>In J2SE or J2EE environments, you may want to use + * <code>newInstance(property, classLoaderCtx)</code> + * where first argument is + * <code>System.getProperty(XmlPullParserFactory.PROPERTY_NAME)</code> + * and second is <code>Thread.getContextClassLoader().getClass()</code> . + * + * @see XmlPullParser + * + * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a> + * @author Stefan Haustein + */ + +public class XmlPullParserFactory { + /** used as default class to server as context class in newInstance() */ + final static Class referenceContextClass; + + static { + XmlPullParserFactory f = new XmlPullParserFactory(); + referenceContextClass = f.getClass(); + } + + /** Name of the system or midlet property that should be used for + a system property containing a comma separated list of factory + or parser class names (value: + org.xmlpull.v1.XmlPullParserFactory). */ + + + public static final String PROPERTY_NAME = + "org.xmlpull.v1.XmlPullParserFactory"; + + private static final String RESOURCE_NAME = + "/META-INF/services/" + PROPERTY_NAME; + + + // public static final String DEFAULT_PROPERTY = + // "org.xmlpull.xpp3.XmlPullParser,org.kxml2.io.KXmlParser"; + + + protected ArrayList parserClasses; + protected String classNamesLocation; + + protected ArrayList serializerClasses; + + + // features are kept there + protected HashMap features = new HashMap(); + + + /** + * Protected constructor to be called by factory implementations. + */ + + protected XmlPullParserFactory() { + } + + + + /** + * Set the features to be set when XML Pull Parser is created by this factory. + * <p><b>NOTE:</b> factory features are not used for XML Serializer. + * + * @param name string with URI identifying feature + * @param state if true feature will be set; if false will be ignored + */ + + public void setFeature(String name, + boolean state) throws XmlPullParserException { + + features.put(name, new Boolean(state)); + } + + + /** + * Return the current value of the feature with given name. + * <p><b>NOTE:</b> factory features are not used for XML Serializer. + * + * @param name The name of feature to be retrieved. + * @return The value of named feature. + * Unknown features are <string>always</strong> returned as false + */ + + public boolean getFeature (String name) { + Boolean value = (Boolean) features.get(name); + return value != null ? value.booleanValue() : false; + } + + /** + * Specifies that the parser produced by this factory will provide + * support for XML namespaces. + * By default the value of this is set to false. + * + * @param awareness true if the parser produced by this code + * will provide support for XML namespaces; false otherwise. + */ + + public void setNamespaceAware(boolean awareness) { + features.put (XmlPullParser.FEATURE_PROCESS_NAMESPACES, new Boolean (awareness)); + } + + /** + * Indicates whether or not the factory is configured to produce + * parsers which are namespace aware + * (it simply set feature XmlPullParser.FEATURE_PROCESS_NAMESPACES to true or false). + * + * @return true if the factory is configured to produce parsers + * which are namespace aware; false otherwise. + */ + + public boolean isNamespaceAware() { + return getFeature (XmlPullParser.FEATURE_PROCESS_NAMESPACES); + } + + + /** + * Specifies that the parser produced by this factory will be validating + * (it simply set feature XmlPullParser.FEATURE_VALIDATION to true or false). + * + * By default the value of this is set to false. + * + * @param validating - if true the parsers created by this factory must be validating. + */ + + public void setValidating(boolean validating) { + features.put (XmlPullParser.FEATURE_VALIDATION, new Boolean (validating)); + } + + /** + * Indicates whether or not the factory is configured to produce parsers + * which validate the XML content during parse. + * + * @return true if the factory is configured to produce parsers + * which validate the XML content during parse; false otherwise. + */ + + public boolean isValidating() { + return getFeature (XmlPullParser.FEATURE_VALIDATION); + } + + /** + * Creates a new instance of a XML Pull Parser + * using the currently configured factory features. + * + * @return A new instance of a XML Pull Parser. + * @throws XmlPullParserException if a parser cannot be created which satisfies the + * requested configuration. + */ + + public XmlPullParser newPullParser() throws XmlPullParserException { + + if (parserClasses == null) throw new XmlPullParserException + ("Factory initialization was incomplete - has not tried "+classNamesLocation); + + if (parserClasses.size() == 0) throw new XmlPullParserException + ("No valid parser classes found in "+classNamesLocation); + + final StringBuffer issues = new StringBuffer (); + + for (int i = 0; i < parserClasses.size(); i++) { + final Class ppClass = (Class) parserClasses.get(i); + try { + final XmlPullParser pp = (XmlPullParser) ppClass.newInstance(); + + for (Iterator iter = features.keySet().iterator(); iter.hasNext(); ) { + final String key = (String) iter.next(); + final Boolean value = (Boolean) features.get(key); + if(value != null && value.booleanValue()) { + pp.setFeature(key, true); + } + } + return pp; + + } catch(Exception ex) { + issues.append (ppClass.getName () + ": "+ ex.toString ()+"; "); + } + } + + throw new XmlPullParserException ("could not create parser: "+issues); + } + + + /** + * Creates a new instance of a XML Serializer. + * + * <p><b>NOTE:</b> factory features are not used for XML Serializer. + * + * @return A new instance of a XML Serializer. + * @throws XmlPullParserException if a parser cannot be created which satisfies the + * requested configuration. + */ + + public XmlSerializer newSerializer() throws XmlPullParserException { + + if (serializerClasses == null) { + throw new XmlPullParserException + ("Factory initialization incomplete - has not tried "+classNamesLocation); + } + if(serializerClasses.size() == 0) { + throw new XmlPullParserException + ("No valid serializer classes found in "+classNamesLocation); + } + + final StringBuffer issues = new StringBuffer (); + + for (int i = 0; i < serializerClasses.size (); i++) { + final Class ppClass = (Class) serializerClasses.get(i); + try { + final XmlSerializer ser = (XmlSerializer) ppClass.newInstance(); + + return ser; + + } catch(Exception ex) { + issues.append (ppClass.getName () + ": "+ ex.toString ()+"; "); + } + } + + throw new XmlPullParserException ("could not create serializer: "+issues); + } + + /** + * Create a new instance of a PullParserFactory that can be used + * to create XML pull parsers (see class description for more + * details). + * + * @return a new instance of a PullParserFactory, as returned by newInstance (null, null); + */ + public static XmlPullParserFactory newInstance () throws XmlPullParserException { + return newInstance(null, null); + } + + public static XmlPullParserFactory newInstance (String classNames, Class context) + throws XmlPullParserException { + + if (context == null) { + //NOTE: make sure context uses the same class loader as API classes + // this is the best we can do without having access to context classloader in J2ME + // if API is in the same classloader as implementation then this will work + context = referenceContextClass; + } + + /* + String classNamesLocation = null; + + if (classNames == null || classNames.length() == 0 || "DEFAULT".equals(classNames)) { + try { + InputStream is = context.getResourceAsStream (RESOURCE_NAME); + + if (is == null) throw new XmlPullParserException + ("resource not found: "+RESOURCE_NAME + +" make sure that parser implementing XmlPull API is available"); + final StringBuffer sb = new StringBuffer(); + + while (true) { + final int ch = is.read(); + if (ch < 0) break; + else if (ch > ' ') + sb.append((char) ch); + } + is.close (); + + classNames = sb.toString (); + } + catch (Exception e) { + throw new XmlPullParserException (null, null, e); + } + classNamesLocation = "resource "+RESOURCE_NAME+" that contained '"+classNames+"'"; + } else { + classNamesLocation = + "parameter classNames to newInstance() that contained '"+classNames+"'"; + } + */ + classNames = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer"; + + XmlPullParserFactory factory = null; + final ArrayList parserClasses = new ArrayList(); + final ArrayList serializerClasses = new ArrayList(); + int pos = 0; + + while (pos < classNames.length ()) { + int cut = classNames.indexOf (',', pos); + + if (cut == -1) cut = classNames.length (); + final String name = classNames.substring (pos, cut); + + Class candidate = null; + Object instance = null; + + try { + candidate = Class.forName (name); + // necessary because of J2ME .class issue + instance = candidate.newInstance (); + } + catch (Exception e) {} + + if (candidate != null) { + boolean recognized = false; + if (instance instanceof XmlPullParser) { + parserClasses.add(candidate); + recognized = true; + } + if (instance instanceof XmlSerializer) { + serializerClasses.add(candidate); + recognized = true; + } + if (instance instanceof XmlPullParserFactory) { + if (factory == null) { + factory = (XmlPullParserFactory) instance; + } + recognized = true; + } + if (!recognized) { + throw new XmlPullParserException ("incompatible class: "+name); + } + } + pos = cut + 1; + } + + if (factory == null) { + factory = new XmlPullParserFactory (); + } + factory.parserClasses = parserClasses; + factory.serializerClasses = serializerClasses; + factory.classNamesLocation = "org.kxml2.io.kXmlParser,org.kxml2.io.KXmlSerializer"; + return factory; + } +} + + diff --git a/xml/src/main/java/org/xmlpull/v1/XmlSerializer.java b/xml/src/main/java/org/xmlpull/v1/XmlSerializer.java new file mode 100644 index 0000000..8e85e2f --- /dev/null +++ b/xml/src/main/java/org/xmlpull/v1/XmlSerializer.java @@ -0,0 +1,326 @@ +package org.xmlpull.v1; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + +/** + * Define an interface to serialziation of XML Infoset. + * This interface abstracts away if serialized XML is XML 1.0 comaptible text or + * other formats of XML 1.0 serializations (such as binary XML for example with WBXML). + * + * <p><b>PLEASE NOTE:</b> This interface will be part of XmlPull 1.2 API. + * It is included as basis for discussion. It may change in any way. + * + * <p>Exceptions that may be thrown are: IOException or runtime exception + * (more runtime exceptions can be thrown but are not declared and as such + * have no semantics defined for this interface): + * <ul> + * <li><em>IllegalArgumentException</em> - for almost all methods to signal that + * argument is illegal + * <li><em>IllegalStateException</em> - to signal that call has good arguments but + * is not expected here (violation of contract) and for features/properties + * when requesting setting unimplemented feature/property + * (UnsupportedOperationException would be better but it is not in MIDP) + * </ul> + * + * <p><b>NOTE:</b> writing CDSECT, ENTITY_REF, IGNORABLE_WHITESPACE, + * PROCESSING_INSTRUCTION, COMMENT, and DOCDECL in some implementations + * may not be supported (for example when serializing to WBXML). + * In such case IllegalStateException will be thrown and it is recommened + * to use an optional feature to signal that implementation is not + * supporting this kind of output. + */ + +public interface XmlSerializer { + + /** + * Set feature identified by name (recommended to be URI for uniqueness). + * Some well known optional features are defined in + * <a href="http://www.xmlpull.org/v1/doc/features.html"> + * http://www.xmlpull.org/v1/doc/features.html</a>. + * + * If feature is not recocgnized or can not be set + * then IllegalStateException MUST be thrown. + * + * @exception IllegalStateException If the feature is not supported or can not be set + */ + void setFeature(String name, + boolean state) + throws IllegalArgumentException, IllegalStateException; + + + /** + * Return the current value of the feature with given name. + * <p><strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null + * + * @param name The name of feature to be retrieved. + * @return The value of named feature. + * @exception IllegalArgumentException if feature string is null + */ + boolean getFeature(String name); + + + /** + * Set the value of a property. + * (the property name is recommened to be URI for uniqueness). + * Some well known optional properties are defined in + * <a href="http://www.xmlpull.org/v1/doc/properties.html"> + * http://www.xmlpull.org/v1/doc/properties.html</a>. + * + * If property is not recocgnized or can not be set + * then IllegalStateException MUST be thrown. + * + * @exception IllegalStateException if the property is not supported or can not be set + */ + void setProperty(String name, + Object value) + throws IllegalArgumentException, IllegalStateException; + + /** + * Look up the value of a property. + * + * The property name is any fully-qualified URI. I + * <p><strong>NOTE:</strong> unknown properties are <string>always</strong> returned as null + * + * @param name The name of property to be retrieved. + * @return The value of named property. + */ + Object getProperty(String name); + + /** + * Set to use binary output stream with given encoding. + */ + void setOutput (OutputStream os, String encoding) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Set the output to the given writer. + * <p><b>WARNING</b> no information about encoding is available! + */ + void setOutput (Writer writer) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Write <?xml declaration with encoding (if encoding not null) + * and standalone flag (if standalone not null) + * This method can only be called just after setOutput. + */ + void startDocument (String encoding, Boolean standalone) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Finish writing. All unclosed start tags will be closed and output + * will be flushed. After calling this method no more output can be + * serialized until next call to setOutput() + */ + void endDocument () + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Binds the given prefix to the given namespace. + * This call is valid for the next element including child elements. + * The prefix and namespace MUST be always declared even if prefix + * is not used in element (startTag() or attribute()) - for XML 1.0 + * it must result in declaring <code>xmlns:prefix='namespace'</code> + * (or <code>xmlns:prefix="namespace"</code> depending what character is used + * to quote attribute value). + * + * <p><b>NOTE:</b> this method MUST be called directly before startTag() + * and if anything but startTag() or setPrefix() is called next there will be exception. + * <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound + * and can not be redefined see: + * <a href="http://www.w3.org/XML/xml-names-19990114-errata#NE05">Namespaces in XML Errata</a>. + * <p><b>NOTE:</b> to set default namespace use as prefix empty string. + * + * @param prefix must be not null (or IllegalArgumentException is thrown) + * @param namespace must be not null + */ + void setPrefix (String prefix, String namespace) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Return namespace that corresponds to given prefix + * If there is no prefix bound to this namespace return null + * but if generatePrefix is false then return generated prefix. + * + * <p><b>NOTE:</b> if the prefix is empty string "" and defualt namespace is bound + * to this prefix then empty string ("") is returned. + * + * <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound + * will have values as defined + * <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML specification</a> + */ + String getPrefix (String namespace, boolean generatePrefix) + throws IllegalArgumentException; + + /** + * Returns the current depth of the element. + * Outside the root element, the depth is 0. The + * depth is incremented by 1 when startTag() is called. + * The depth is decremented after the call to endTag() + * event was observed. + * + * <pre> + * <!-- outside --> 0 + * <root> 1 + * sometext 1 + * <foobar> 2 + * </foobar> 2 + * </root> 1 + * <!-- outside --> 0 + * </pre> + */ + int getDepth(); + + /** + * Returns the namespace URI of the current element as set by startTag(). + * + * <p><b>NOTE:</b> that measn in particaulr that: <ul> + * <li>if there was startTag("", ...) then getNamespace() returns "" + * <li>if there was startTag(null, ...) then getNamespace() returns null + * </ul> + * + * @return namespace set by startTag() that is currently in scope + */ + String getNamespace (); + + /** + * Returns the name of the current element as set by startTag(). + * It can only be null before first call to startTag() + * or when last endTag() is called to close first startTag(). + * + * @return namespace set by startTag() that is currently in scope + */ + String getName(); + + /** + * Writes a start tag with the given namespace and name. + * If there is no prefix defined for the given namespace, + * a prefix will be defined automatically. + * The explicit prefixes for namespaces can be established by calling setPrefix() + * immediately before this method. + * If namespace is null no namespace prefix is printed but just name. + * If namespace is empty string then serialzier will make sure that + * default empty namespace is declared (in XML 1.0 xmlns='') + * or throw IllegalStateException if default namespace is already bound + * to non-empty string. + */ + XmlSerializer startTag (String namespace, String name) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Write an attribute. Calls to attribute() MUST follow a call to + * startTag() immediately. If there is no prefix defined for the + * given namespace, a prefix will be defined automatically. + * If namespace is null or empty string + * no namespace prefix is printed but just name. + */ + XmlSerializer attribute (String namespace, String name, String value) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Write end tag. Repetition of namespace and name is just for avoiding errors. + * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were + * very difficult to find... + * If namespace is null no namespace prefix is printed but just name. + * If namespace is empty string then serialzier will make sure that + * default empty namespace is declared (in XML 1.0 xmlns=''). + */ + XmlSerializer endTag (String namespace, String name) + throws IOException, IllegalArgumentException, IllegalStateException; + + + // /** + // * Writes a start tag with the given namespace and name. + // * <br />If there is no prefix defined (prefix == null) for the given namespace, + // * a prefix will be defined automatically. + // * <br />If explicit prefixes is passed (prefix != null) then it will be used + // *and namespace declared if not already declared or + // * throw IllegalStateException the same prefix was already set on this + // * element (setPrefix()) and was bound to different namespace. + // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown. + // * <br />If namespace is null then no namespace prefix is printed but just name. + // * <br />If namespace is empty string then serializer will make sure that + // * default empty namespace is declared (in XML 1.0 xmlns='') + // * or throw IllegalStateException if default namespace is already bound + // * to non-empty string. + // */ + // XmlSerializer startTag (String prefix, String namespace, String name) + // throws IOException, IllegalArgumentException, IllegalStateException; + // + // /** + // * Write an attribute. Calls to attribute() MUST follow a call to + // * startTag() immediately. + // * <br />If there is no prefix defined (prefix == null) for the given namespace, + // * a prefix will be defined automatically. + // * <br />If explicit prefixes is passed (prefix != null) then it will be used + // * and namespace declared if not already declared or + // * throw IllegalStateException the same prefix was already set on this + // * element (setPrefix()) and was bound to different namespace. + // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown. + // * <br />If namespace is null then no namespace prefix is printed but just name. + // * <br />If namespace is empty string then serializer will make sure that + // * default empty namespace is declared (in XML 1.0 xmlns='') + // * or throw IllegalStateException if default namespace is already bound + // * to non-empty string. + // */ + // XmlSerializer attribute (String prefix, String namespace, String name, String value) + // throws IOException, IllegalArgumentException, IllegalStateException; + // + // /** + // * Write end tag. Repetition of namespace, prefix, and name is just for avoiding errors. + // * <br />If namespace or name arguments are different from corresponding startTag call + // * then IllegalArgumentException is thrown, if prefix argument is not null and is different + // * from corresponding starTag then IllegalArgumentException is thrown. + // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown. + // * <br />If namespace is null then no namespace prefix is printed but just name. + // * <br />If namespace is empty string then serializer will make sure that + // * default empty namespace is declared (in XML 1.0 xmlns=''). + // * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were + // * very difficult to find...</p> + // */ + // ALEK: This is really optional as prefix in end tag MUST correspond to start tag but good for error checking + // XmlSerializer endTag (String prefix, String namespace, String name) + // throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Writes text, where special XML chars are escaped automatically + */ + XmlSerializer text (String text) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Writes text, where special XML chars are escaped automatically + */ + XmlSerializer text (char [] buf, int start, int len) + throws IOException, IllegalArgumentException, IllegalStateException; + + void cdsect (String text) + throws IOException, IllegalArgumentException, IllegalStateException; + void entityRef (String text) throws IOException, + IllegalArgumentException, IllegalStateException; + void processingInstruction (String text) + throws IOException, IllegalArgumentException, IllegalStateException; + void comment (String text) + throws IOException, IllegalArgumentException, IllegalStateException; + void docdecl (String text) + throws IOException, IllegalArgumentException, IllegalStateException; + void ignorableWhitespace (String text) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** + * Write all pending output to the stream. + * If method startTag() or attribute() was called then start tag is closed (final >) + * before flush() is called on underlying output stream. + * + * <p><b>NOTE:</b> if there is need to close start tag + * (so no more attribute() calls are allowed) but without flushinging output + * call method text() with empty string (text("")). + * + */ + void flush () + throws IOException; + +} + diff --git a/xml/src/main/java/org/xmlpull/v1/sax2/Driver.java b/xml/src/main/java/org/xmlpull/v1/sax2/Driver.java new file mode 100644 index 0000000..0bd2d4f --- /dev/null +++ b/xml/src/main/java/org/xmlpull/v1/sax2/Driver.java @@ -0,0 +1,469 @@ +/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ +// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) + +package org.xmlpull.v1.sax2; + +import java.io.InputStream; +import java.io.IOException; +import java.io.Reader; + +// not J2ME classes -- remove if you want to run in MIDP devices +import java.net.URL; +import java.net.MalformedURLException; + + +// not J2ME classes +import java.io.FileInputStream; +import java.io.FileNotFoundException; + +import org.xml.sax.Attributes; +import org.xml.sax.DTDHandler; +import org.xml.sax.ContentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +/** + * SAX2 Driver that pulls events from XmlPullParser + * and comverts them into SAX2 callbacks. + * + * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a> + */ + +public class Driver implements Locator, XMLReader, Attributes +{ + + protected static final String DECLARATION_HANDLER_PROPERTY = + "http://xml.org/sax/properties/declaration-handler"; + + protected static final String LEXICAL_HANDLER_PROPERTY = + "http://xml.org/sax/properties/lexical-handler"; + + protected static final String NAMESPACES_FEATURE = + "http://xml.org/sax/features/namespaces"; + + protected static final String NAMESPACE_PREFIXES_FEATURE = + "http://xml.org/sax/features/namespace-prefixes"; + + protected static final String VALIDATION_FEATURE = + "http://xml.org/sax/features/validation"; + + protected static final String APACHE_SCHEMA_VALIDATION_FEATURE = + "http://apache.org/xml/features/validation/schema"; + + protected static final String APACHE_DYNAMIC_VALIDATION_FEATURE = + "http://apache.org/xml/features/validation/dynamic"; + + protected ContentHandler contentHandler = new DefaultHandler(); + protected ErrorHandler errorHandler = new DefaultHandler();; + + protected String systemId; + + protected XmlPullParser pp; + + //private final static boolean DEBUG = false; + + /** + */ + public Driver() throws XmlPullParserException { + final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + factory.setNamespaceAware(true); + pp = factory.newPullParser(); + } + + public Driver(XmlPullParser pp) throws XmlPullParserException { + this.pp = pp; + } + + // -- Attributes interface + + public int getLength() { return pp.getAttributeCount(); } + public String getURI(int index) { return pp.getAttributeNamespace(index); } + public String getLocalName(int index) { return pp.getAttributeName(index); } + public String getQName(int index) { + final String prefix = pp.getAttributePrefix(index); + if(prefix != null) { + return prefix+':'+pp.getAttributeName(index); + } else { + return pp.getAttributeName(index); + } + } + public String getType(int index) { return pp.getAttributeType(index); } + public String getValue(int index) { return pp.getAttributeValue(index); } + + public int getIndex(String uri, String localName) { + for (int i = 0; i < pp.getAttributeCount(); i++) + { + if(pp.getAttributeNamespace(i).equals(uri) + && pp.getAttributeName(i).equals(localName)) + { + return i; + } + + } + return -1; + } + + public int getIndex(String qName) { + for (int i = 0; i < pp.getAttributeCount(); i++) + { + if(pp.getAttributeName(i).equals(qName)) + { + return i; + } + + } + return -1; + } + + public String getType(String uri, String localName) { + for (int i = 0; i < pp.getAttributeCount(); i++) + { + if(pp.getAttributeNamespace(i).equals(uri) + && pp.getAttributeName(i).equals(localName)) + { + return pp.getAttributeType(i); + } + + } + return null; + } + public String getType(String qName) { + for (int i = 0; i < pp.getAttributeCount(); i++) + { + if(pp.getAttributeName(i).equals(qName)) + { + return pp.getAttributeType(i); + } + + } + return null; + } + public String getValue(String uri, String localName) { + return pp.getAttributeValue(uri, localName); + } + public String getValue(String qName) { + return pp.getAttributeValue(null, qName); + } + + // -- Locator interface + + public String getPublicId() { return null; } + public String getSystemId() { return systemId; } + public int getLineNumber() { return pp.getLineNumber(); } + public int getColumnNumber() { return pp.getColumnNumber(); } + + // --- XMLReader interface + + public boolean getFeature(String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if(NAMESPACES_FEATURE.equals(name)) { + return pp.getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES); + } else if(NAMESPACE_PREFIXES_FEATURE.equals(name)) { + return pp.getFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES); + } else if(VALIDATION_FEATURE.equals(name)) { + return pp.getFeature(XmlPullParser.FEATURE_VALIDATION); + // } else if(APACHE_SCHEMA_VALIDATION_FEATURE.equals(name)) { + // return false; //TODO + // } else if(APACHE_DYNAMIC_VALIDATION_FEATURE.equals(name)) { + // return false; //TODO + } else { + return pp.getFeature(name); + //throw new SAXNotRecognizedException("unrecognized feature "+name); + } + } + + public void setFeature (String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + try { + if(NAMESPACES_FEATURE.equals(name)) { + pp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, value); + } else if(NAMESPACE_PREFIXES_FEATURE.equals(name)) { + if(pp.getFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES) != value) { + pp.setFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES, value); + } + } else if(VALIDATION_FEATURE.equals(name)) { + pp.setFeature(XmlPullParser.FEATURE_VALIDATION, value); + // } else if(APACHE_SCHEMA_VALIDATION_FEATURE.equals(name)) { + // // can ignore as validation must be false ... + // // if(true == value) { + // // throw new SAXNotSupportedException("schema validation is not supported"); + // // } + // } else if(APACHE_DYNAMIC_VALIDATION_FEATURE.equals(name)) { + // if(true == value) { + // throw new SAXNotSupportedException("dynamic validation is not supported"); + // } + } else { + pp.setFeature(name, value); + //throw new SAXNotRecognizedException("unrecognized feature "+name); + } + } catch(XmlPullParserException ex) { + // throw new SAXNotSupportedException("problem with setting feature "+name+": "+ex); + } + } + + public Object getProperty (String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + if(DECLARATION_HANDLER_PROPERTY.equals(name)) { + return null; + } else if(LEXICAL_HANDLER_PROPERTY.equals(name)) { + return null; + } else { + return pp.getProperty(name); + //throw new SAXNotRecognizedException("not recognized get property "+name); + } + } + + public void setProperty (String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + // + if(DECLARATION_HANDLER_PROPERTY.equals(name)) { + throw new SAXNotSupportedException("not supported setting property "+name);//+" to "+value); + } else if(LEXICAL_HANDLER_PROPERTY.equals(name)) { + throw new SAXNotSupportedException("not supported setting property "+name);//+" to "+value); + } else { + try { + pp.setProperty(name, value); + } catch(XmlPullParserException ex) { + throw new SAXNotSupportedException("not supported set property "+name+": "+ ex); + } + //throw new SAXNotRecognizedException("not recognized set property "+name); + } + } + + public void setEntityResolver (EntityResolver resolver) {} + + public EntityResolver getEntityResolver () { return null; } + + public void setDTDHandler (DTDHandler handler) {} + + public DTDHandler getDTDHandler () { return null; } + + public void setContentHandler (ContentHandler handler) + { + this.contentHandler = handler; + } + + public ContentHandler getContentHandler() { return contentHandler; } + + public void setErrorHandler(ErrorHandler handler) { + this.errorHandler = handler; + } + + public ErrorHandler getErrorHandler() { return errorHandler; } + + public void parse(InputSource source) throws SAXException, IOException + { + + systemId = source.getSystemId(); + contentHandler.setDocumentLocator(this); + + final Reader reader = source.getCharacterStream(); + try { + if (reader == null) { + InputStream stream = source.getByteStream(); + final String encoding = source.getEncoding(); + + if (stream == null) { + systemId = source.getSystemId(); + if(systemId == null) { + SAXParseException saxException = new SAXParseException( + "null source systemId" , this); + errorHandler.fatalError(saxException); + return; + } + // NOTE: replace with Connection to run in J2ME environment + try { + final URL url = new URL(systemId); + stream = url.openStream(); + } catch (MalformedURLException nue) { + try { + stream = new FileInputStream(systemId); + } catch (FileNotFoundException fnfe) { + final SAXParseException saxException = new SAXParseException( + "could not open file with systemId "+systemId, this, fnfe); + errorHandler.fatalError(saxException); + return; + } + } + } + pp.setInput(stream, encoding); + } else { + pp.setInput(reader); + } + } catch (XmlPullParserException ex) { + final SAXParseException saxException = new SAXParseException( + "parsing initialization error: "+ex, this, ex); + //if(DEBUG) ex.printStackTrace(); + errorHandler.fatalError(saxException); + return; + } + + // start parsing - move to first start tag + try { + contentHandler.startDocument(); + // get first event + pp.next(); + // it should be start tag... + if(pp.getEventType() != XmlPullParser.START_TAG) { + final SAXParseException saxException = new SAXParseException( + "expected start tag not"+pp.getPositionDescription(), this); + //throw saxException; + errorHandler.fatalError(saxException); + return; + } + } catch (XmlPullParserException ex) { + final SAXParseException saxException = new SAXParseException( + "parsing initialization error: "+ex, this, ex); + //ex.printStackTrace(); + errorHandler.fatalError(saxException); + return; + } + + // now real parsing can start! + + parseSubTree(pp); + + // and finished ... + + contentHandler.endDocument(); + } + + public void parse(String systemId) throws SAXException, IOException { + parse(new InputSource(systemId)); + } + + + public void parseSubTree(XmlPullParser pp) throws SAXException, IOException { + this.pp = pp; + final boolean namespaceAware = pp.getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES); + try { + if(pp.getEventType() != XmlPullParser.START_TAG) { + throw new SAXException( + "start tag must be read before skiping subtree"+pp.getPositionDescription()); + } + final int[] holderForStartAndLength = new int[2]; + final StringBuffer rawName = new StringBuffer(16); + String prefix = null; + String name = null; + int level = pp.getDepth() - 1; + int type = XmlPullParser.START_TAG; + + LOOP: + do { + switch(type) { + case XmlPullParser.START_TAG: + if(namespaceAware) { + final int depth = pp.getDepth() - 1; + final int countPrev = + (level > depth) ? pp.getNamespaceCount(depth) : 0; + //int countPrev = pp.getNamespaceCount(pp.getDepth() - 1); + final int count = pp.getNamespaceCount(depth + 1); + for (int i = countPrev; i < count; i++) + { + contentHandler.startPrefixMapping( + pp.getNamespacePrefix(i), + pp.getNamespaceUri(i) + ); + } + name = pp.getName(); + prefix = pp.getPrefix(); + if(prefix != null) { + rawName.setLength(0); + rawName.append(prefix); + rawName.append(':'); + rawName.append(name); + } + startElement(pp.getNamespace(), + name, + // TODO Fixed this. Was "not equals". + prefix == null ? name : rawName.toString()); + } else { + startElement(pp.getNamespace(), + pp.getName(), + pp.getName()); + } + //++level; + + break; + case XmlPullParser.TEXT: + final char[] chars = pp.getTextCharacters(holderForStartAndLength); + contentHandler.characters(chars, + holderForStartAndLength[0], //start + holderForStartAndLength[1] //len + ); + break; + case XmlPullParser.END_TAG: + //--level; + if(namespaceAware) { + name = pp.getName(); + prefix = pp.getPrefix(); + if(prefix != null) { + rawName.setLength(0); + rawName.append(prefix); + rawName.append(':'); + rawName.append(name); + } + contentHandler.endElement(pp.getNamespace(), + name, + prefix != null ? name : rawName.toString() + ); + // when entering show prefixes for all levels!!!! + final int depth = pp.getDepth(); + final int countPrev = + (level > depth) ? pp.getNamespaceCount(pp.getDepth()) : 0; + int count = pp.getNamespaceCount(pp.getDepth() - 1); + // undeclare them in reverse order + for (int i = count - 1; i >= countPrev; i--) + { + contentHandler.endPrefixMapping( + pp.getNamespacePrefix(i) + ); + } + } else { + contentHandler.endElement(pp.getNamespace(), + pp.getName(), + pp.getName() + ); + + } + break; + case XmlPullParser.END_DOCUMENT: + break LOOP; + } + type = pp.next(); + } while(pp.getDepth() > level); + } catch (XmlPullParserException ex) { + final SAXParseException saxException = new SAXParseException("parsing error: "+ex, this, ex); + ex.printStackTrace(); + errorHandler.fatalError(saxException); + } + } + + /** + * Calls {@link ContentHandler#startElement(String, String, String, Attributes) startElement} + * on the <code>ContentHandler</code> with <code>this</code> driver object as the + * {@link Attributes} implementation. In default implementation + * {@link Attributes} object is valid only during this method call and may not + * be stored. Sub-classes can overwrite this method to cache attributes. + */ + protected void startElement(String namespace, String localName, String qName) throws SAXException { + contentHandler.startElement(namespace, localName, qName, this); + } + +} diff --git a/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp new file mode 100644 index 0000000..7149272 --- /dev/null +++ b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp @@ -0,0 +1,1530 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ExpatParser" + +#include "jni.h" +#include "utils/Log.h" +#include "JNIHelp.h" + +#include <string.h> +#include <utils/misc.h> +#include <expat.h> +#include <cutils/jstring.h> + +#define BUCKET_COUNT 128 + +/** + * Wrapper around an interned string. + */ +typedef struct { + + /** The interned string itself. */ + jstring interned; + + /** UTF-8 equivalent of the interned string. */ + const char* bytes; + + /** Hash code of the interned string. */ + int hash; +} InternedString; + +/** + * Keeps track of strings between start and end events. + */ +typedef struct { + + jstring* array; + int capacity; + int size; +} StringStack; + +/** + * Data passed to parser handler method by the parser. + */ +typedef struct { + + /** + * The JNI environment for the current thread. This should only be used + * to keep a reference to the env for use in Expat callbacks. + */ + JNIEnv* env; + + /** The Java parser object. */ + jobject object; + + /** Buffer for text events. */ + jcharArray buffer; + + /** The size of our buffer in jchars. */ + int bufferSize; + + /** Current attributes. */ + const char** attributes; + + /** Number of attributes. */ + int attributeCount; + + /** True if namespace support is enabled. */ + bool processNamespaces; + + /** Keep track of names. */ + StringStack stringStack; + + /** Cache of interned strings. */ + InternedString** internedStrings[BUCKET_COUNT]; +} ParsingContext; + +static jmethodID startElementMethod; +static jmethodID endElementMethod; +static jmethodID textMethod; +static jmethodID commentMethod; +static jmethodID startCdataMethod; +static jmethodID endCdataMethod; +static jmethodID startDtdMethod; +static jmethodID endDtdMethod; +static jmethodID startNamespaceMethod; +static jmethodID endNamespaceMethod; +static jmethodID processingInstructionMethod; +static jmethodID handleExternalEntityMethod; +static jmethodID internMethod; +static jclass stringClass; +static jstring emptyString; + +/** + * Throws a NullPointerException. + * + * @param msg exception message + */ +static void throw_NullPointerException(JNIEnv* env, const char* msg) { + jniThrowException(env, "java/lang/NullPointerException", msg); +} + +/** + * Throw a NullPointerException. + */ +static void throw_OutOfMemoryError(JNIEnv* env) { + jniThrowException(env, "java/lang/OutOfMemoryError", "Out of memory."); +} + +/** + * Calculates a hash code for a null-terminated string. This is *not* equivalent + * to Java's String.hashCode(). This hashes the bytes while String.hashCode() + * hashes UTF-16 chars. + * + * @param s null-terminated string to hash + * @returns hash code + */ +static int hashString(const char* s) { + int hash = 0; + if (s) { + while (*s) { + hash = hash * 31 + *s++; + } + } + return hash; +} + +/** + * Creates a new interned string wrapper. Looks up the interned string + * representing the given UTF-8 bytes. + * + * @param bytes null-terminated string to intern + * @param hash of bytes + * @returns wrapper of interned Java string + */ +static InternedString* newInternedString(JNIEnv* env, + ParsingContext* parsingContext, const char* bytes, int hash) { + // Allocate a new wrapper. + InternedString* wrapper + = (InternedString* ) malloc(sizeof(InternedString)); + if (wrapper == NULL) { + throw_OutOfMemoryError(env); + return NULL; + } + + // Create a copy of the UTF-8 bytes. + // TODO: sometimes we already know the length. Reuse it if so. + char* copy = strdup(bytes); + wrapper->bytes = copy; + if (wrapper->bytes == NULL) { + throw_OutOfMemoryError(env); + free(wrapper); + return NULL; + } + + // Save the hash. + wrapper->hash = hash; + + // To intern a string, we must first create a new string and then call + // intern() on it. We then keep a global reference to the interned string. + jstring newString = env->NewStringUTF(bytes); + if (env->ExceptionCheck()) { + free(copy); + free(wrapper); + return NULL; + } + + // Call intern(). + jstring interned = + (jstring) env->CallObjectMethod(newString, internMethod); + if (env->ExceptionCheck()) { + free(copy); + free(wrapper); + return NULL; + } + + // Create a global reference to the interned string. + wrapper->interned = (jstring) env->NewGlobalRef(interned); + if (env->ExceptionCheck()) { + free(copy); + free(wrapper); + return NULL; + } + + env->DeleteLocalRef(interned); + env->DeleteLocalRef(newString); + + return wrapper; +} + +/** + * Allocates a new bucket with one entry. + * + * @param entry to store in the bucket + * @returns a reference to the bucket + */ +static InternedString** newInternedStringBucket(InternedString* entry) { + InternedString** bucket + = (InternedString**) malloc(sizeof(InternedString*) * 2); + if (bucket == NULL) return NULL; + + bucket[0] = entry; + bucket[1] = NULL; + return bucket; +} + +/** + * Expands an interned string bucket and adds the given entry. Frees the + * provided bucket and returns a new one. + * + * @param existingBucket the bucket to replace + * @param entry to add to the bucket + * @returns a reference to the newly-allocated bucket containing the given entry + */ +static InternedString** expandInternedStringBucket( + InternedString** existingBucket, InternedString* entry) { + // Determine the size of the existing bucket. + int size = 0; + while (existingBucket[size]) size++; + + // Allocate the new bucket with enough space for one more entry and + // a null terminator. + InternedString** newBucket = (InternedString**) realloc(existingBucket, + sizeof(InternedString*) * (size + 2)); + if (newBucket == NULL) return NULL; + + newBucket[size] = entry; + newBucket[size + 1] = NULL; + + return newBucket; +} + +/** + * Returns an interned string for the given UTF-8 string. + * + * @param bucket to search for s + * @param s null-terminated string to find + * @param hash of s + * @returns interned Java string equivalent of s or null if not found + */ +static jstring findInternedString(InternedString** bucket, const char* s, + int hash) { + InternedString* current; + while ((current = *(bucket++)) != NULL) { + if (current->hash != hash) continue; + if (!strcmp(s, current->bytes)) return current->interned; + } + return NULL; +} + +/** + * Returns an interned string for the given UTF-8 string. + * + * @param s null-terminated string to intern + * @returns interned Java string equivelent of s or NULL if s is null + */ +static jstring internString(JNIEnv* env, ParsingContext* parsingContext, + const char* s) { + if (s == NULL) return NULL; + + int hash = hashString(s); + int bucketIndex = hash & (BUCKET_COUNT - 1); + + InternedString*** buckets = parsingContext->internedStrings; + InternedString** bucket = buckets[bucketIndex]; + InternedString* internedString; + + if (bucket) { + // We have a bucket already. Look for the given string. + jstring found = findInternedString(bucket, s, hash); + if (found) { + // We found it! + return found; + } + + // We didn't find it. :( + // Create a new entry. + internedString = newInternedString(env, parsingContext, s, hash); + if (internedString == NULL) return NULL; + + // Expand the bucket. + bucket = expandInternedStringBucket(bucket, internedString); + if (bucket == NULL) { + throw_OutOfMemoryError(env); + return NULL; + } + + buckets[bucketIndex] = bucket; + + return internedString->interned; + } else { + // We don't even have a bucket yet. Create an entry. + internedString = newInternedString(env, parsingContext, s, hash); + if (internedString == NULL) return NULL; + + // Create a new bucket with one entry. + bucket = newInternedStringBucket(internedString); + if (bucket == NULL) { + throw_OutOfMemoryError(env); + return NULL; + } + + buckets[bucketIndex] = bucket; + + return internedString->interned; + } +} + +/** + * Returns an interned string for the given UTF-8 string. + * + * @param s string to intern + * @param length of s + * @returns interned Java string equivelent of s + */ +static jstring internStringOfLength(JNIEnv* env, ParsingContext* parsingContext, + const char* s, int length) { + // Create a null-terminated version. + char nullTerminated[length + 1]; + memcpy(nullTerminated, s, length); + nullTerminated[length] = 0; + + return internString(env, parsingContext, nullTerminated); +} + +/** + * Throw an assertion error. + * + * @param message to show + */ +static void fail(JNIEnv* env, const char* message) { + jclass clazz; + clazz = env->FindClass("java/lang/AssertionError"); + env->ThrowNew(clazz, message); +} + +/** + * Allocates a new parsing context. + * + * @param jobject the Java ExpatParser instance + * @returns a newly-allocated ParsingContext + */ +ParsingContext* newParsingContext(JNIEnv* env, jobject object) { + ParsingContext* result = (ParsingContext*) malloc(sizeof(ParsingContext)); + if (result == NULL) { + throw_OutOfMemoryError(env); + return NULL; + } + + result->env = NULL; + result->buffer = NULL; + result->bufferSize = -1; + result->object = object; + + int stackSize = 10; + result->stringStack.capacity = stackSize; + result->stringStack.size = 0; + result->stringStack.array + = (jstring*) malloc(stackSize * sizeof(jstring)); + + for (int i = 0; i < BUCKET_COUNT; i++) { + result->internedStrings[i] = NULL; + } + + return result; +} + +/** + * Frees the char[] buffer if it exists. + */ +static void freeBuffer(JNIEnv* env, ParsingContext* parsingContext) { + if (parsingContext->buffer != NULL) { + env->DeleteGlobalRef(parsingContext->buffer); + parsingContext->buffer = NULL; + parsingContext->bufferSize = -1; + } +} + +/** + * Ensures our buffer is big enough. + * + * @param length in jchars + * @returns a reference to the buffer + */ +static jcharArray ensureCapacity(ParsingContext* parsingContext, int length) { + if (parsingContext->bufferSize < length) { + JNIEnv* env = parsingContext->env; + + // Free the existing char[]. + freeBuffer(env, parsingContext); + + // Allocate a new char[]. + jcharArray javaBuffer = env->NewCharArray(length); + if (javaBuffer == NULL) return NULL; + + // Create a global reference. + javaBuffer = (jcharArray) env->NewGlobalRef(javaBuffer); + if (javaBuffer == NULL) return NULL; + + parsingContext->buffer = javaBuffer; + parsingContext->bufferSize = length; + } + + return parsingContext->buffer; +} + +/** + * Copies UTF-8 characters into the buffer. Returns the number of Java chars + * which were buffered. + * + * @param characters to copy into the buffer + * @param length of characters to copy (in bytes) + * @returns number of UTF-16 characters which were copied + */ +static size_t fillBuffer(ParsingContext* parsingContext, const char* characters, + int length) { + JNIEnv* env = parsingContext->env; + + // Grow buffer if necessary. + jcharArray buffer = ensureCapacity(parsingContext, length); + if (buffer == NULL) return -1; + + // Get a native reference to our buffer. + jchar* nativeBuffer = env->GetCharArrayElements(buffer, NULL); + + // Decode UTF-8 characters into our buffer. + size_t utf16length; + strcpylen8to16((char16_t*) nativeBuffer, characters, length, &utf16length); + + // Release our native reference. + env->ReleaseCharArrayElements(buffer, nativeBuffer, 0); + + return utf16length; +} + +/** + * Buffers the given text and passes it to the given method. + * + * @param method to pass the characters and length to with signature + * (char[], int) + * @param data parsing context + * @param text to copy into the buffer + * @param length of text to copy (in bytes) + */ +static void bufferAndInvoke(jmethodID method, void* data, const char* text, + size_t length) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + // Buffer the element name. + size_t utf16length = fillBuffer(parsingContext, text, length); + + // Invoke given method. + jobject javaParser = parsingContext->object; + jcharArray buffer = parsingContext->buffer; + env->CallVoidMethod(javaParser, method, buffer, utf16length); +} + +/** + * Finds the '|' in a null-terminated string. Returns -1 if none is found. + * + * @param s string to search + * @returns index of the separator + */ +static int findSeparator(const char* s) { + char* pointer = strchr(s, '|'); + return pointer == NULL ? -1 : pointer - s; +} + +/** + * Parses the URI out of an Expat element name and turns it into a Java string. + * Expat element names follow the format: "uri|localName". + * + * @param s string to parse from + * @param separatorIndex index of separator in s + * @returns interned Java string containing the URI + */ +static jstring parseUri(JNIEnv* env, ParsingContext* parsingContext, const char* s, + int separatorIndex) { + return separatorIndex == -1 ? emptyString + : internStringOfLength(env, parsingContext, s, separatorIndex); +} + +/** + * Parses the local name out of an Expat element name and turns it into a Java + * string. Expat element names follow the format: "uri|localName". + * + * @param s string to parse from + * @param separatorIndex index of separator in s + * @returns interned Java string containing the local name + */ +static jstring parseLocalName(JNIEnv* env, ParsingContext* parsingContext, + const char* s, int separatorIndex) { + return internString(env, parsingContext, s + separatorIndex + 1); +} + +/** + * Pushes a string onto the stack. + */ +static void stringStackPush(ParsingContext* parsingContext, jstring s) { + StringStack* stringStack = &parsingContext->stringStack; + + // Expand if necessary. + if (stringStack->size == stringStack->capacity) { + int newCapacity = stringStack->capacity * 2; + stringStack->array = (jstring*) realloc(stringStack->array, + newCapacity * sizeof(jstring)); + + if (stringStack->array == NULL) { + throw_OutOfMemoryError(parsingContext->env); + return; + } + + stringStack->capacity = newCapacity; + } + + stringStack->array[stringStack->size++] = s; +} + +/** + * Pops a string off the stack. + */ +static jstring stringStackPop(ParsingContext* parsingContext) { + StringStack* stringStack = &parsingContext->stringStack; + + if (stringStack->size == 0) { + return NULL; + } + + return stringStack->array[--stringStack->size]; +} + +/** + * Called by Expat at the start of an element. Delegates to the same method + * on the Java parser. + * + * @param data parsing context + * @param elementName "uri|localName" or "localName" for the current element + * @param attributes alternating attribute names and values. Like element + * names, attribute names follow the format "uri|localName" or "localName". + */ +static void startElement(void* data, const char* elementName, + const char** attributes) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + // Count the number of attributes. + int count = 0; + while (attributes[count << 1]) count++; + + // Make the attributes available for the duration of this call. + parsingContext->attributes = attributes; + parsingContext->attributeCount = count; + + jobject javaParser = parsingContext->object; + + if (parsingContext->processNamespaces) { + // Break down Expat's element name into two Java strings. + int separatorIndex = findSeparator(elementName); + jstring uri = parseUri( + env, parsingContext, elementName, separatorIndex); + jstring localName = parseLocalName( + env, parsingContext, elementName, separatorIndex); + + stringStackPush(parsingContext, uri); + stringStackPush(parsingContext, localName); + + env->CallVoidMethod(javaParser, startElementMethod, uri, localName, + emptyString, attributes, count); + } else { + jstring qName = internString(env, parsingContext, elementName); + + stringStackPush(parsingContext, qName); + + env->CallVoidMethod(javaParser, startElementMethod, + emptyString, emptyString, qName, attributes, count); + } + + parsingContext->attributes = NULL; + parsingContext->attributeCount = -1; +} + +/** + * Called by Expat at the end of an element. Delegates to the same method + * on the Java parser. + * + * @param data parsing context + * @param elementName "uri|localName" or "localName" for the current element + */ +static void endElement(void* data, const char* elementName) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + jobject javaParser = parsingContext->object; + + if (parsingContext->processNamespaces) { + jstring localName = stringStackPop(parsingContext); + jstring uri = stringStackPop(parsingContext); + + env->CallVoidMethod(javaParser, endElementMethod, uri, localName, + emptyString); + } else { + jstring qName = stringStackPop(parsingContext); + + env->CallVoidMethod(javaParser, endElementMethod, + emptyString, emptyString, qName); + } +} + +/** + * Called by Expat when it encounters text. Delegates to the same method + * on the Java parser. This may be called mutiple times with incremental pieces + * of the same contiguous block of text. + * + * @param data parsing context + * @param characters buffer containing encountered text + * @param length number of characters in the buffer + */ +static void text(void* data, const char* characters, int length) { + bufferAndInvoke(textMethod, data, characters, length); +} + +/** + * Called by Expat when it encounters a comment. Delegates to the same method + * on the Java parser. + + * @param data parsing context + * @param comment 0-terminated + */ +static void comment(void* data, const char* comment) { + bufferAndInvoke(commentMethod, data, comment, strlen(comment)); +} + +/** + * Called by Expat at the beginning of a namespace mapping. + * + * @param data parsing context + * @param prefix null-terminated namespace prefix used in the XML + * @param uri of the namespace + */ +static void startNamespace(void* data, const char* prefix, const char* uri) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + jstring internedPrefix = emptyString; + if (prefix != NULL) { + internedPrefix = internString(env, parsingContext, prefix); + if (env->ExceptionCheck()) return; + } + + jstring internedUri = emptyString; + if (uri != NULL) { + internedUri = internString(env, parsingContext, uri); + if (env->ExceptionCheck()) return; + } + + stringStackPush(parsingContext, internedPrefix); + + jobject javaParser = parsingContext->object; + env->CallVoidMethod(javaParser, startNamespaceMethod, internedPrefix, + internedUri); +} + +/** + * Called by Expat at the end of a namespace mapping. + * + * @param data parsing context + * @param prefix null-terminated namespace prefix used in the XML + */ +static void endNamespace(void* data, const char* prefix) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + jstring internedPrefix = stringStackPop(parsingContext); + + jobject javaParser = parsingContext->object; + env->CallVoidMethod(javaParser, endNamespaceMethod, internedPrefix); +} + +/** + * Called by Expat at the beginning of a CDATA section. + * + * @param data parsing context + */ +static void startCdata(void* data) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + jobject javaParser = parsingContext->object; + env->CallVoidMethod(javaParser, startCdataMethod); +} + +/** + * Called by Expat at the end of a CDATA section. + * + * @param data parsing context + */ +static void endCdata(void* data) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + jobject javaParser = parsingContext->object; + env->CallVoidMethod(javaParser, endCdataMethod); +} + +/** + * Called by Expat at the beginning of a DOCTYPE section. + * + * @param data parsing context + */ +static void startDtd(void* data, const char* name, + const char* systemId, const char* publicId, int hasInternalSubset) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + jstring javaName = internString(env, parsingContext, name); + if (env->ExceptionCheck()) return; + + jstring javaPublicId = internString(env, parsingContext, publicId); + if (env->ExceptionCheck()) return; + + jstring javaSystemId = internString(env, parsingContext, systemId); + if (env->ExceptionCheck()) return; + + jobject javaParser = parsingContext->object; + env->CallVoidMethod(javaParser, startDtdMethod, javaName, javaPublicId, + javaSystemId); +} + +/** + * Called by Expat at the end of a DOCTYPE section. + * + * @param data parsing context + */ +static void endDtd(void* data) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + jobject javaParser = parsingContext->object; + env->CallVoidMethod(javaParser, endDtdMethod); +} + +/** + * Called by Expat when it encounters processing instructions. + * + * @param data parsing context + * @param target of the instruction + * @param instructionData + */ +static void processingInstruction(void* data, const char* target, + const char* instructionData) { + ParsingContext* parsingContext = (ParsingContext*) data; + JNIEnv* env = parsingContext->env; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) return; + + jstring javaTarget = internString(env, parsingContext, target); + if (env->ExceptionCheck()) return; + + jstring javaInstructionData = env->NewStringUTF(instructionData); + if (env->ExceptionCheck()) return; + + jobject javaParser = parsingContext->object; + env->CallVoidMethod(javaParser, processingInstructionMethod, javaTarget, + javaInstructionData); + + // We have to temporarily clear an exception before we can release local + // references. + jthrowable exception = env->ExceptionOccurred(); + if (exception != NULL) { + env->ExceptionClear(); + } + + env->DeleteLocalRef(javaInstructionData); + + if (exception != NULL) { + env->Throw(exception); + } +} + +/** + * Creates a new entity parser. + * + * @param object the Java ExpatParser instance + * @param parentParser pointer + * @param javaEncoding the character encoding name + * @param javaContext that was provided to handleExternalEntity + * @returns the pointer to the C Expat entity parser + */ +static jint createEntityParser(JNIEnv* env, jobject object, jint parentParser, + jstring javaEncoding, jstring javaContext) { + const char* encoding = env->GetStringUTFChars(javaEncoding, NULL); + if (encoding == NULL) { + return 0; + } + + const char* context = env->GetStringUTFChars(javaContext, NULL); + if (context == NULL) { + env->ReleaseStringUTFChars(javaEncoding, encoding); + return 0; + } + + XML_Parser parent = (XML_Parser) parentParser; + XML_Parser entityParser + = XML_ExternalEntityParserCreate(parent, context, NULL); + env->ReleaseStringUTFChars(javaEncoding, encoding); + env->ReleaseStringUTFChars(javaContext, context); + + if (entityParser == NULL) { + throw_OutOfMemoryError(env); + } + + return (jint) entityParser; +} + +/** + * Handles external entities. We ignore the "base" URI and keep track of it + * ourselves. + */ +static int handleExternalEntity(XML_Parser parser, const char* context, + const char* ignored, const char* systemId, const char* publicId) { + ParsingContext* parsingContext = (ParsingContext*) XML_GetUserData(parser); + jobject javaParser = parsingContext->object; + JNIEnv* env = parsingContext->env; + jobject object = parsingContext->object; + + // Bail out if a previously called handler threw an exception. + if (env->ExceptionCheck()) { + return XML_STATUS_ERROR; + } + + jstring javaSystemId = env->NewStringUTF(systemId); + if (env->ExceptionCheck()) { + return XML_STATUS_ERROR; + } + jstring javaPublicId = env->NewStringUTF(publicId); + if (env->ExceptionCheck()) { + return XML_STATUS_ERROR; + } + jstring javaContext = env->NewStringUTF(context); + if (env->ExceptionCheck()) { + return XML_STATUS_ERROR; + } + + // Pass the wrapped parser and both strings to java. + env->CallVoidMethod(javaParser, handleExternalEntityMethod, javaContext, + javaPublicId, javaSystemId); + + /* + * Parsing the external entity leaves parsingContext->env and object set to + * NULL, so we need to restore both. + * + * TODO: consider restoring the original env and object instead of setting + * them to NULL in the append() functions. + */ + parsingContext->env = env; + parsingContext->object = object; + + env->DeleteLocalRef(javaSystemId); + env->DeleteLocalRef(javaPublicId); + env->DeleteLocalRef(javaContext); + + return env->ExceptionCheck() ? XML_STATUS_ERROR : XML_STATUS_OK; +} + +/** + * Releases the parsing context. + */ +static void releaseParsingContext(JNIEnv* env, ParsingContext* context) { + free(context->stringStack.array); + + freeBuffer(env, context); + + // Free interned string cache. + for (int i = 0; i < BUCKET_COUNT; i++) { + if (context->internedStrings[i]) { + InternedString** bucket = context->internedStrings[i]; + InternedString* current; + while ((current = *(bucket++)) != NULL) { + // Free the UTF-8 bytes. + free((void*) (current->bytes)); + + // Free the interned string reference. + env->DeleteGlobalRef(current->interned); + + // Free the bucket. + free(current); + } + + // Free the buckets. + free(context->internedStrings[i]); + } + } + + free(context); +} + +/** + * Creates a new Expat parser. Called from the Java ExpatParser contructor. + * + * @param object the Java ExpatParser instance + * @param javaEncoding the character encoding name + * @param processNamespaces true if the parser should handle namespaces + * @returns the pointer to the C Expat parser + */ +static jint initialize(JNIEnv* env, jobject object, jstring javaEncoding, + jboolean processNamespaces) { + // Allocate parsing context. + ParsingContext* context = newParsingContext(env, object); + if (context == NULL) { + return 0; + } + + context->processNamespaces = (bool) processNamespaces; + + // Create a parser. + XML_Parser parser; + const char* encoding = env->GetStringUTFChars(javaEncoding, NULL); + if (processNamespaces) { + // Use '|' to separate URIs from local names. + parser = XML_ParserCreateNS(encoding, '|'); + } else { + parser = XML_ParserCreate(encoding); + } + env->ReleaseStringUTFChars(javaEncoding, encoding); + + if (parser != NULL) { + if (processNamespaces) { + XML_SetNamespaceDeclHandler(parser, startNamespace, endNamespace); + } + + XML_SetCommentHandler(parser, comment); + XML_SetCdataSectionHandler(parser, startCdata, endCdata); + + XML_SetElementHandler(parser, startElement, endElement); + XML_SetCharacterDataHandler(parser, text); + XML_SetDoctypeDeclHandler(parser, startDtd, endDtd); + XML_SetProcessingInstructionHandler(parser, processingInstruction); + XML_SetExternalEntityRefHandler(parser, handleExternalEntity); + + XML_SetUserData(parser, context); + } else { + releaseParsingContext(env, context); + throw_OutOfMemoryError(env); + return 0; + } + + return (jint) parser; +} + +/** + * Passes some XML to the parser. + * + * @param object the Java ExpatParser instance + * @param pointer to the C expat parser + * @param xml Java string containing an XML snippet + * @param isFinal whether or not this is the last snippet; enables more error + * checking, i.e. is the document complete? + */ +static void appendString(JNIEnv* env, jobject object, jint pointer, jstring xml, + jboolean isFinal) { + XML_Parser parser = (XML_Parser) pointer; + ParsingContext* context = (ParsingContext*) XML_GetUserData(parser); + context->env = env; + context->object = object; + + int length = env->GetStringLength(xml) << 1; // in bytes + const jchar* characters = env->GetStringChars(xml, NULL); + + if (!XML_Parse(parser, (char*) characters, length, isFinal) + && !env->ExceptionCheck()) { + jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException"); + const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser)); + env->ThrowNew(clazz, errorMessage); + } + + // We have to temporarily clear an exception before we can release local + // references. + jthrowable exception = env->ExceptionOccurred(); + if (exception) { + env->ExceptionClear(); + env->ReleaseStringChars(xml, characters); + env->Throw(exception); + } else { + env->ReleaseStringChars(xml, characters); + } + + context->object = NULL; + context->env = NULL; +} + +/** + * Passes some XML to the parser. + * + * @param object the Java ExpatParser instance + * @param pointer to the C expat parser + * @param xml Java char[] containing XML + * @param offset into the xml buffer + * @param length of text in the xml buffer + */ +static void appendCharacters(JNIEnv* env, jobject object, jint pointer, + jcharArray xml, jint offset, jint length) { + XML_Parser parser = (XML_Parser) pointer; + ParsingContext* context = (ParsingContext*) XML_GetUserData(parser); + context->env = env; + context->object = object; + + jchar* characters = env->GetCharArrayElements(xml, NULL); + + if (!XML_Parse(parser, ((char*) characters) + (offset << 1), + length << 1, XML_FALSE) && !env->ExceptionCheck()) { + jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException"); + const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser)); + env->ThrowNew(clazz, errorMessage); + } + + // We have to temporarily clear an exception before we can release local + // references. + jthrowable exception = env->ExceptionOccurred(); + if (exception) { + env->ExceptionClear(); + env->ReleaseCharArrayElements(xml, characters, JNI_ABORT); + env->Throw(exception); + } else { + env->ReleaseCharArrayElements(xml, characters, JNI_ABORT); + } + + context->object = NULL; + context->env = NULL; +} + +/** + * Passes some XML to the parser. + * + * @param object the Java ExpatParser instance + * @param pointer to the C expat parser + * @param xml Java byte[] containing XML + * @param offset into the xml buffer + * @param length of text in the xml buffer + */ +static void appendBytes(JNIEnv* env, jobject object, jint pointer, + jbyteArray xml, jint offset, jint length) { + XML_Parser parser = (XML_Parser) pointer; + ParsingContext* context = (ParsingContext*) XML_GetUserData(parser); + context->env = env; + context->object = object; + + jbyte* bytes = env->GetByteArrayElements(xml, NULL); + + if (!XML_Parse(parser, ((char*) bytes) + offset, length, XML_FALSE) + && !env->ExceptionCheck()) { + jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException"); + const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser)); + env->ThrowNew(clazz, errorMessage); + } + + // We have to temporarily clear an exception before we can release local + // references. + jthrowable exception = env->ExceptionOccurred(); + if (exception) { + env->ExceptionClear(); + env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT); + env->Throw(exception); + } else { + env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT); + } + + context->object = NULL; + context->env = NULL; +} + +/** + * Releases parser only. + * + * @param object the Java ExpatParser instance + * @param i pointer to the C expat parser + */ +static void releaseParser(JNIEnv* env, jobject object, jint i) { + XML_Parser parser = (XML_Parser) i; + XML_ParserFree(parser); +} + +/** + * Cleans up after the parser. Called at garbage collection time. + * + * @param object the Java ExpatParser instance + * @param i pointer to the C expat parser + */ +static void release(JNIEnv* env, jobject object, jint i) { + XML_Parser parser = (XML_Parser) i; + + ParsingContext* context = (ParsingContext*) XML_GetUserData(parser); + releaseParsingContext(env, context); + + XML_ParserFree(parser); +} + +/** + * Gets the current line. + * + * @param object the Java ExpatParser instance + * @param pointer to the C expat parser + * @returns current line number + */ +static int line(JNIEnv* env, jobject clazz, jint pointer) { + XML_Parser parser = (XML_Parser) pointer; + return XML_GetCurrentLineNumber(parser); +} + +/** + * Gets the current column. + * + * @param object the Java ExpatParser instance + * @param pointer to the C expat parser + * @returns current column number + */ +static int column(JNIEnv* env, jobject clazz, jint pointer) { + XML_Parser parser = (XML_Parser) pointer; + return XML_GetCurrentColumnNumber(parser); +} + +/** + * Gets the URI of the attribute at the given index. + * + * @param object Java ExpatParser instance + * @param pointer to the C expat parser + * @param attributePointer to the attribute array + * @param index of the attribute + * @returns interned Java string containing attribute's URI + */ +static jstring getAttributeURI(JNIEnv* env, jobject clazz, jint pointer, + jint attributePointer, jint index) { + XML_Parser parser = (XML_Parser) pointer; + ParsingContext* context = (ParsingContext*) XML_GetUserData(parser); + + if (!context->processNamespaces) { + return emptyString; + } + + const char** attributes = (const char**) attributePointer; + + const char* name = attributes[index << 1]; + int separatorIndex = findSeparator(name); + return parseUri(env, context, name, separatorIndex); +} + +/** + * Gets the local name of the attribute at the given index. + * + * @param object Java ExpatParser instance + * @param pointer to the C expat parser + * @param attributePointer to the attribute array + * @param index of the attribute + * @returns interned Java string containing attribute's local name + */ +static jstring getAttributeLocalName(JNIEnv* env, jobject clazz, jint pointer, + jint attributePointer, jint index) { + XML_Parser parser = (XML_Parser) pointer; + ParsingContext* context = (ParsingContext*) XML_GetUserData(parser); + + if (!context->processNamespaces) { + return emptyString; + } + + const char** attributes = (const char**) attributePointer; + const char* name = attributes[index << 1]; + + int separatorIndex = findSeparator(name); + return parseLocalName(env, context, name, separatorIndex); +} + +/** + * Gets the qualified name of the attribute at the given index. + * + * @param object Java ExpatParser instance + * @param pointer to the C expat parser + * @param attributePointer to the attribute array + * @param index of the attribute + * @returns interned Java string containing attribute's local name + */ +static jstring getAttributeQName(JNIEnv* env, jobject clazz, jint pointer, + jint attributePointer, jint index) { + XML_Parser parser = (XML_Parser) pointer; + ParsingContext* context = (ParsingContext*) XML_GetUserData(parser); + + if (context->processNamespaces) { + return emptyString; + } + + const char** attributes = (const char**) attributePointer; + + const char* name = attributes[index << 1]; + return internString(env, context, name); +} + +/** + * Gets the value of the attribute at the given index. + * + * @param object Java ExpatParser instance + * @param attributePointer to the attribute array + * @param index of the attribute + * @returns Java string containing attribute's value + */ +static jstring getAttributeValueByIndex(JNIEnv* env, jobject clazz, + jint attributePointer, jint index) { + const char** attributes = (const char**) attributePointer; + const char* value = attributes[(index << 1) + 1]; + return env->NewStringUTF(value); +} + +/** + * Searches the attributes for the given name and returns the attribute's + * index or -1 if not found. + * + * @param attributes alternating name/value pairs + * @param name of attribute to look for + * @returns index of found attribute or -1 if not found + */ +static jint findAttributeByName(const char** attributes, + const char* name) { + int index; + for (index = 0; attributes[index]; index += 2) { + if (strcmp(attributes[index], name) == 0) + return index >> 1; + } + + // Not found. + return -1; +} + +/** + * Gets the index of the attribute with the given qualified name. + * + * @param attributePointer to the attribute array + * @param qName to look for + * @returns index of attribute with the given uri and local name or -1 if not + * found + */ +static jint getAttributeIndexForQName(JNIEnv* env, jobject clazz, + jint attributePointer, jstring qName) { + const char** attributes = (const char**) attributePointer; + int length = env->GetStringUTFLength(qName); + + const char* qNameBytes = env->GetStringUTFChars(qName, NULL); + if (qNameBytes == NULL) return -1; + int found = findAttributeByName(attributes, qNameBytes); + env->ReleaseStringUTFChars(qName, qNameBytes); + return found; +} + +/** + * Gets the index of the attribute with the given URI and name. + * + * @param attributePointer to the attribute array + * @param uri to look for + * @param localName to look for + * @returns index of attribute with the given uri and local name or -1 if not + * found + */ +static jint getAttributeIndex(JNIEnv* env, jobject clazz, + jint attributePointer, jstring uri, jstring localName) { + const char** attributes = (const char**) attributePointer; + int uriLength = env->GetStringUTFLength(uri); + + if (uriLength == 0) { + // If there's no URI, then a local name works just like a qName. + return getAttributeIndexForQName( + env, clazz, attributePointer, localName); + } + + int localNameLength = env->GetStringUTFLength(localName); + + // Create string in the same format used by Expat: "uri|localName" + char concatenated[uriLength + localNameLength + 2]; + + // Append uri. + const char* uriBytes = env->GetStringUTFChars(uri, NULL); + if (uriBytes == NULL) return -1; + strcpy(concatenated, uriBytes); + env->ReleaseStringUTFChars(uri, uriBytes); + + // Separarator. + concatenated[uriLength] = '|'; + + // Append local name. + const char* localNameBytes = env->GetStringUTFChars(localName, NULL); + if (localNameBytes == NULL) return -1; + strcpy(concatenated + uriLength + 1, localNameBytes); + env->ReleaseStringUTFChars(localName, localNameBytes); + + return findAttributeByName(attributes, concatenated); +} + +/** + * Gets the value of the attribute with the given qualified name. + * + * @param attributePointer to the attribute array + * @param uri to look for + * @param localName to look for + * @returns value of attribute with the given uri and local name or NULL if not + * found + */ +static jstring getAttributeValueForQName(JNIEnv* env, jobject clazz, + jint attributePointer, jstring qName) { + jint index = getAttributeIndexForQName( + env, clazz, attributePointer, qName); + return index == -1 ? NULL + : getAttributeValueByIndex(env, clazz, attributePointer, index); +} + +/** + * Gets the value of the attribute with the given URI and name. + * + * @param attributePointer to the attribute array + * @param uri to look for + * @param localName to look for + * @returns value of attribute with the given uri and local name or NULL if not + * found + */ +static jstring getAttributeValue(JNIEnv* env, jobject clazz, + jint attributePointer, jstring uri, jstring localName) { + jint index = getAttributeIndex( + env, clazz, attributePointer, uri, localName); + return index == -1 ? NULL + : getAttributeValueByIndex(env, clazz, attributePointer, index); +} + +/** + * Clones an array of strings. Uses one contiguous block of memory so as to + * maximize performance. + */ +static char** cloneStrings(const char** source, int count) { + // Figure out how big the buffer needs to be. + int arraySize = (count + 1) * sizeof(char*); + int totalSize = arraySize; + int stringLengths[count]; + for (int i = 0; i < count; i++) { + int length = strlen(source[i]); + stringLengths[i] = length; + totalSize += length + 1; + } + + char* buffer = (char*) malloc(totalSize); + if (buffer == NULL) { + return NULL; + } + + // Array is at the beginning of the buffer. + char** clonedArray = (char**) buffer; + clonedArray[count] = NULL; // null terminate + + // First string is immediately after. + char* destinationString = buffer + arraySize; + + for (int i = 0; i < count; i++) { + const char* sourceString = source[i]; + int stringLength = stringLengths[i]; + memcpy(destinationString, sourceString, stringLength + 1); + clonedArray[i] = destinationString; + destinationString += stringLength + 1; + } + + return clonedArray; +} + +/** + * Clones attributes. + * + * @param pointer to char** to clone + * @param count number of attributes + */ +static jint cloneAttributes(JNIEnv* env, jobject clazz, + jint pointer, jint count) { + return (int) cloneStrings((const char**) pointer, count << 1); +} + +/** + * Frees cloned attributes. + */ +static void freeAttributes(JNIEnv* env, jobject clazz, jint pointer) { + free((void*) pointer); +} + +/** + * Called when we initialize our Java parser class. + * + * @param clazz Java ExpatParser class + */ +static void staticInitialize(JNIEnv* env, jobject clazz, jstring empty) { + startElementMethod = env->GetMethodID((jclass) clazz, "startElement", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V"); + if (startElementMethod == NULL) return; + + endElementMethod = env->GetMethodID((jclass) clazz, "endElement", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (endElementMethod == NULL) return; + + textMethod = env->GetMethodID((jclass) clazz, "text", "([CI)V"); + if (textMethod == NULL) return; + + commentMethod = env->GetMethodID((jclass) clazz, "comment", "([CI)V"); + if (commentMethod == NULL) return; + + startCdataMethod = env->GetMethodID((jclass) clazz, "startCdata", "()V"); + if (startCdataMethod == NULL) return; + + endCdataMethod = env->GetMethodID((jclass) clazz, "endCdata", "()V"); + if (endCdataMethod == NULL) return; + + startDtdMethod = env->GetMethodID((jclass) clazz, "startDtd", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (startDtdMethod == NULL) return; + + endDtdMethod = env->GetMethodID((jclass) clazz, "endDtd", "()V"); + if (endDtdMethod == NULL) return; + + startNamespaceMethod = env->GetMethodID((jclass) clazz, "startNamespace", + "(Ljava/lang/String;Ljava/lang/String;)V"); + if (startNamespaceMethod == NULL) return; + + endNamespaceMethod = env->GetMethodID((jclass) clazz, "endNamespace", + "(Ljava/lang/String;)V"); + if (endNamespaceMethod == NULL) return; + + processingInstructionMethod = env->GetMethodID((jclass) clazz, + "processingInstruction", "(Ljava/lang/String;Ljava/lang/String;)V"); + if (processingInstructionMethod == NULL) return; + + handleExternalEntityMethod = env->GetMethodID((jclass) clazz, + "handleExternalEntity", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (handleExternalEntityMethod == NULL) return; + + // Look up String class. + stringClass = env->FindClass("java/lang/String"); + + internMethod = env->GetMethodID(stringClass, "intern", + "()Ljava/lang/String;"); + if (internMethod == NULL) return; + + // Reference to "". + emptyString = (jstring) env->NewGlobalRef(empty); +} + +static JNINativeMethod parserMethods[] = { + { "line", "(I)I", (void*) line }, + { "column", "(I)I", (void*) column }, + { "release", "(I)V", (void*) release }, + { "releaseParser", "(I)V", (void*) releaseParser }, + { "append", "(ILjava/lang/String;Z)V", (void*) appendString }, + { "append", "(I[CII)V", (void*) appendCharacters }, + { "append", "(I[BII)V", (void*) appendBytes }, + { "initialize", "(Ljava/lang/String;Z)I", + (void*) initialize}, + { "createEntityParser", "(ILjava/lang/String;Ljava/lang/String;)I", + (void*) createEntityParser}, + { "staticInitialize", "(Ljava/lang/String;)V", (void*) staticInitialize}, + { "cloneAttributes", "(II)I", (void*) cloneAttributes }, +}; + +static JNINativeMethod attributeMethods[] = { + { "getURI", "(III)Ljava/lang/String;", (void*) getAttributeURI }, + { "getLocalName", "(III)Ljava/lang/String;", (void*) getAttributeLocalName }, + { "getQName", "(III)Ljava/lang/String;", (void*) getAttributeQName }, + { "getValue", "(II)Ljava/lang/String;", (void*) getAttributeValueByIndex }, + { "getIndex", "(ILjava/lang/String;Ljava/lang/String;)I", + (void*) getAttributeIndex }, + { "getIndex", "(ILjava/lang/String;)I", + (void*) getAttributeIndexForQName }, + { "getValue", "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;", + (void*) getAttributeValue }, + { "getValue", "(ILjava/lang/String;)Ljava/lang/String;", + (void*) getAttributeValueForQName }, + { "freeAttributes", "(I)V", (void*) freeAttributes }, +}; + +/** + * Called from Register.c. + */ +extern "C" int register_org_apache_harmony_xml_ExpatParser(JNIEnv* env) { + int result = jniRegisterNativeMethods(env, "org/apache/harmony/xml/ExpatParser", + parserMethods, NELEM(parserMethods)); + if (result != 0) { + return result; + } + + return jniRegisterNativeMethods(env, "org/apache/harmony/xml/ExpatAttributes", + attributeMethods, NELEM(attributeMethods)); +} diff --git a/xml/src/main/native/sub.mk b/xml/src/main/native/sub.mk new file mode 100644 index 0000000..e48d12e --- /dev/null +++ b/xml/src/main/native/sub.mk @@ -0,0 +1,20 @@ +# This file is included by the top-level libcore Android.mk. +# It's not a normal makefile, so we don't include CLEAR_VARS +# or BUILD_*_LIBRARY. + +LOCAL_SRC_FILES := org_apache_harmony_xml_ExpatParser.cpp + +LOCAL_C_INCLUDES += \ + external/expat/lib + +# Any shared/static libs that are listed here must also +# be listed in libs/nativehelper/Android.mk. +# TODO: fix this requirement + +LOCAL_SHARED_LIBRARIES += \ + libcutils \ + libexpat \ + libutils + +#LOCAL_STATIC_LIBRARIES += + diff --git a/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java b/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java new file mode 100644 index 0000000..480bca3 --- /dev/null +++ b/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java @@ -0,0 +1,839 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xml; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.kxml2.io.KXmlParser; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.ext.DefaultHandler2; +import org.xml.sax.helpers.DefaultHandler; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.net.ServerSocket; +import java.net.Socket; + +public class ExpatParserTest extends TestCase { + + private static final String SNIPPET = "<dagny dad=\"bob\">hello</dagny>"; + + public void testExceptions() { + // From startElement(). + ContentHandler contentHandler = new DefaultHandler() { + @Override + public void startElement(String uri, String localName, + String qName, Attributes attributes) + throws SAXException { + throw new SAXException(); + } + }; + try { + parse(SNIPPET, contentHandler); + fail(); + } catch (SAXException checked) { /* expected */ } + + // From endElement(). + contentHandler = new DefaultHandler() { + @Override + public void endElement(String uri, String localName, + String qName) + throws SAXException { + throw new SAXException(); + } + }; + try { + parse(SNIPPET, contentHandler); + fail(); + } catch (SAXException checked) { /* expected */ } + + // From characters(). + contentHandler = new DefaultHandler() { + @Override + public void characters(char ch[], int start, int length) + throws SAXException { + throw new SAXException(); + } + }; + try { + parse(SNIPPET, contentHandler); + fail(); + } catch (SAXException checked) { /* expected */ } + } + + public void testSax() { + try { + // Parse String. + TestHandler handler = new TestHandler(); + parse(SNIPPET, handler); + validate(handler); + + // Parse Reader. + handler = new TestHandler(); + parse(new StringReader(SNIPPET), handler); + validate(handler); + + // Parse InputStream. + handler = new TestHandler(); + parse(new ByteArrayInputStream(SNIPPET.getBytes()), + Encoding.UTF_8, handler); + validate(handler); + } catch (SAXException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + static void validate(TestHandler handler) { + assertEquals("dagny", handler.startElementName); + assertEquals("dagny", handler.endElementName); + assertEquals("hello", handler.text.toString()); + } + + static class TestHandler extends DefaultHandler { + + String startElementName; + String endElementName; + StringBuilder text = new StringBuilder(); + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + + assertNull(this.startElementName); + this.startElementName = localName; + + // Validate attributes. + assertEquals(1, attributes.getLength()); + assertEquals("", attributes.getURI(0)); + assertEquals("dad", attributes.getLocalName(0)); + assertEquals("bob", attributes.getValue(0)); + assertEquals(0, attributes.getIndex("", "dad")); + assertEquals("bob", attributes.getValue("", "dad")); + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException { + assertNull(this.endElementName); + this.endElementName = localName; + } + + @Override + public void characters(char ch[], int start, int length) + throws SAXException { + this.text.append(ch, start, length); + } + } + + public void testPullParser() { + try { + XmlPullParser parser = newPullParser(); + + // Test reader. + parser.setInput(new StringReader(SNIPPET)); + validate(parser); + + // Test input stream. + parser.setInput(new ByteArrayInputStream(SNIPPET.getBytes()), + "UTF-8"); + validate(parser); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + static void validate(XmlPullParser parser) + throws XmlPullParserException, IOException { + assertEquals(XmlPullParser.START_DOCUMENT, parser.getEventType()); + + assertEquals(0, parser.getDepth()); + + assertEquals(XmlPullParser.START_TAG, parser.next()); + + assertEquals(1, parser.getDepth()); + + assertEquals("dagny", parser.getName()); + assertEquals(1, parser.getAttributeCount()); + assertEquals("dad", parser.getAttributeName(0)); + assertEquals("bob", parser.getAttributeValue(0)); + assertEquals("bob", parser.getAttributeValue(null, "dad")); + + assertEquals(XmlPullParser.TEXT, parser.next()); + + assertEquals(1, parser.getDepth()); + + assertEquals("hello", parser.getText()); + + assertEquals(XmlPullParser.END_TAG, parser.next()); + + assertEquals(1, parser.getDepth()); + + assertEquals("dagny", parser.getName()); + + assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); + + assertEquals(0, parser.getDepth()); + } + + static final String XML = + "<one xmlns='ns:default' xmlns:n1='ns:1' a='b'>\n" + + " <n1:two c='d' n1:e='f' xmlns:n2='ns:2'>text</n1:two>\n" + + "</one>"; + + public void testExpatPullParserNamespaces() throws Exception { + XmlPullParser pullParser = newPullParser(); + pullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + pullParser.setInput(new StringReader(XML)); + testPullParserNamespaces(pullParser); + } + + public void testKxmlPullParserNamespaces() throws Exception { + XmlPullParser pullParser = new KXmlParser(); + pullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + pullParser.setInput(new StringReader(XML)); + testPullParserNamespaces(pullParser); + } + + private void testPullParserNamespaces(XmlPullParser parser) throws Exception { + assertEquals(0, parser.getDepth()); + assertEquals(0, parser.getNamespaceCount(0)); + + try { + parser.getNamespaceCount(1); + fail(); + } catch (IndexOutOfBoundsException e) { /* expected */ } + + // one + assertEquals(XmlPullParser.START_TAG, parser.next()); + assertEquals(1, parser.getDepth()); + + checkNamespacesInOne(parser); + + // n1:two + assertEquals(XmlPullParser.START_TAG, parser.nextTag()); + + assertEquals(2, parser.getDepth()); + checkNamespacesInTwo(parser); + + // Body of two. + assertEquals(XmlPullParser.TEXT, parser.next()); + + // End of two. + assertEquals(XmlPullParser.END_TAG, parser.nextTag()); + + // Depth should still be 2. + assertEquals(2, parser.getDepth()); + + // We should still be able to see the namespaces from two. + checkNamespacesInTwo(parser); + + // End of one. + assertEquals(XmlPullParser.END_TAG, parser.nextTag()); + + // Depth should be back to 1. + assertEquals(1, parser.getDepth()); + + // We can still see the namespaces in one. + checkNamespacesInOne(parser); + + // We shouldn't be able to see the namespaces in two anymore. + try { + parser.getNamespaceCount(2); + fail(); + } catch (IndexOutOfBoundsException e) { /* expected */ } + + assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); + + // We shouldn't be able to see the namespaces in one anymore. + try { + parser.getNamespaceCount(1); + fail(); + } catch (IndexOutOfBoundsException e) { /* expected */ } + + assertEquals(0, parser.getNamespaceCount(0)); + } + + private void checkNamespacesInOne(XmlPullParser parser) throws XmlPullParserException { + assertEquals(2, parser.getNamespaceCount(1)); + + // Prefix for default namespace is null. + assertNull(parser.getNamespacePrefix(0)); + assertEquals("ns:default", parser.getNamespaceUri(0)); + + assertEquals("n1", parser.getNamespacePrefix(1)); + assertEquals("ns:1", parser.getNamespaceUri(1)); + + assertEquals("ns:default", parser.getNamespace(null)); + + // KXML returns null. + // assertEquals("ns:default", parser.getNamespace("")); + } + + private void checkNamespacesInTwo(XmlPullParser parser) throws XmlPullParserException { + // These should still be valid. + checkNamespacesInOne(parser); + + assertEquals(3, parser.getNamespaceCount(2)); + + // Default ns should still be in the stack + assertNull(parser.getNamespacePrefix(0)); + assertEquals("ns:default", parser.getNamespaceUri(0)); + } + + public void testNamespaces() { + try { + NamespaceHandler handler = new NamespaceHandler(); + parse(XML, handler); + handler.validate(); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + static class NamespaceHandler implements ContentHandler { + + Locator locator; + boolean documentStarted; + boolean documentEnded; + Map<String, String> prefixMappings = new HashMap<String, String>(); + + boolean oneStarted; + boolean twoStarted; + boolean oneEnded; + boolean twoEnded; + + public void validate() { + assertTrue(documentEnded); + } + + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + public void startDocument() throws SAXException { + documentStarted = true; + assertNotNull(locator); + assertEquals(0, prefixMappings.size()); + assertFalse(documentEnded); + } + + public void endDocument() throws SAXException { + assertTrue(documentStarted); + assertTrue(oneEnded); + assertTrue(twoEnded); + assertEquals(0, prefixMappings.size()); + documentEnded = true; + } + + public void startPrefixMapping(String prefix, String uri) + throws SAXException { + prefixMappings.put(prefix, uri); + } + + public void endPrefixMapping(String prefix) throws SAXException { + assertNotNull(prefixMappings.remove(prefix)); + } + + public void startElement(String uri, String localName, String qName, + Attributes atts) throws SAXException { + + if (localName == "one") { + assertEquals(2, prefixMappings.size()); + + assertEquals(1, locator.getLineNumber()); + + assertFalse(oneStarted); + assertFalse(twoStarted); + assertFalse(oneEnded); + assertFalse(twoEnded); + + oneStarted = true; + + assertSame("ns:default", uri); + // TODO The result of the RI is "one" + assertEquals("", qName); + + // Check atts. + assertEquals(1, atts.getLength()); + + assertSame("", atts.getURI(0)); + assertSame("a", atts.getLocalName(0)); + assertEquals("b", atts.getValue(0)); + assertEquals(0, atts.getIndex("", "a")); + assertEquals("b", atts.getValue("", "a")); + + return; + } + + if (localName == "two") { + assertEquals(3, prefixMappings.size()); + + assertTrue(oneStarted); + assertFalse(twoStarted); + assertFalse(oneEnded); + assertFalse(twoEnded); + + twoStarted = true; + + assertSame("ns:1", uri); + // TODO The result of the RI is "n1:two" + Assert.assertEquals("", qName); + + // Check atts. + assertEquals(2, atts.getLength()); + + assertSame("", atts.getURI(0)); + assertSame("c", atts.getLocalName(0)); + assertEquals("d", atts.getValue(0)); + assertEquals(0, atts.getIndex("", "c")); + assertEquals("d", atts.getValue("", "c")); + + assertSame("ns:1", atts.getURI(1)); + assertSame("e", atts.getLocalName(1)); + assertEquals("f", atts.getValue(1)); + assertEquals(1, atts.getIndex("ns:1", "e")); + assertEquals("f", atts.getValue("ns:1", "e")); + + // We shouldn't find these. + assertEquals(-1, atts.getIndex("ns:default", "e")); + assertEquals(null, atts.getValue("ns:default", "e")); + + return; + } + + fail(); + } + + public void endElement(String uri, String localName, String qName) + throws SAXException { + if (localName == "one") { + assertEquals(3, locator.getLineNumber()); + + assertTrue(oneStarted); + assertTrue(twoStarted); + assertTrue(twoEnded); + assertFalse(oneEnded); + + oneEnded = true; + + assertSame("ns:default", uri); + assertEquals("", qName); + + return; + } + + if (localName == "two") { + assertTrue(oneStarted); + assertTrue(twoStarted); + assertFalse(twoEnded); + assertFalse(oneEnded); + + twoEnded = true; + + assertSame("ns:1", uri); + assertEquals("", qName); + + return; + } + + fail(); + } + + public void characters(char ch[], int start, int length) + throws SAXException { + String s = new String(ch, start, length).trim(); + + if (!s.equals("")) { + assertTrue(oneStarted); + assertTrue(twoStarted); + assertFalse(oneEnded); + assertFalse(twoEnded); + assertEquals("text", s); + } + } + + public void ignorableWhitespace(char ch[], int start, int length) + throws SAXException { + fail(); + } + + public void processingInstruction(String target, String data) + throws SAXException { + fail(); + } + + public void skippedEntity(String name) throws SAXException { + fail(); + } + } + + public void testDtd() throws Exception { + Reader in = new StringReader( + "<?xml version=\"1.0\"?><!DOCTYPE foo PUBLIC 'bar' 'tee'><a></a>"); + ExpatReader reader = new ExpatReader(); + TestDtdHandler handler = new TestDtdHandler(); + reader.setContentHandler(handler); + reader.setLexicalHandler(handler); + reader.parse(new InputSource(in)); + + assertEquals("foo", handler.name); + assertEquals("bar", handler.publicId); + assertEquals("tee", handler.systemId); + + assertTrue(handler.ended); + } + + static class TestDtdHandler extends DefaultHandler2 { + + String name; + String publicId; + String systemId; + + boolean ended; + + Locator locator; + + @Override + public void startDTD(String name, String publicId, String systemId) { + this.name = name; + this.publicId = publicId; + this.systemId = systemId; + } + + @Override + public void endDTD() { + ended = true; + } + + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + } + + public void testCdata() throws Exception { + Reader in = new StringReader( + "<a><![CDATA[<b></b>]]> <![CDATA[<c></c>]]></a>"); + + ExpatReader reader = new ExpatReader(); + TestCdataHandler handler = new TestCdataHandler(); + reader.setContentHandler(handler); + reader.setLexicalHandler(handler); + + reader.parse(new InputSource(in)); + + assertEquals(2, handler.startCdata); + assertEquals(2, handler.endCdata); + assertEquals("<b></b> <c></c>", handler.buffer.toString()); + } + + static class TestCdataHandler extends DefaultHandler2 { + + int startCdata, endCdata; + StringBuffer buffer = new StringBuffer(); + + @Override + public void characters(char ch[], int start, int length) { + buffer.append(ch, start, length); + } + + @Override + public void startCDATA() throws SAXException { + startCdata++; + } + + @Override + public void endCDATA() throws SAXException { + endCdata++; + } + } + + public void testProcessingInstructions() throws IOException, SAXException { + Reader in = new StringReader( + "<?bob lee?><a></a>"); + + ExpatReader reader = new ExpatReader(); + TestProcessingInstrutionHandler handler + = new TestProcessingInstrutionHandler(); + reader.setContentHandler(handler); + + reader.parse(new InputSource(in)); + + assertEquals("bob", handler.target); + assertEquals("lee", handler.data); + } + + static class TestProcessingInstrutionHandler extends DefaultHandler2 { + + String target; + String data; + + @Override + public void processingInstruction(String target, String data) { + this.target = target; + this.data = data; + } + } + + public void testExternalEntity() throws IOException, SAXException { + class Handler extends DefaultHandler { + + List<String> elementNames = new ArrayList<String>(); + StringBuilder text = new StringBuilder(); + + public InputSource resolveEntity(String publicId, String systemId) + throws IOException, SAXException { + if (publicId.equals("publicA") && systemId.equals("systemA")) { + return new InputSource(new StringReader("<a/>")); + } else if (publicId.equals("publicB") + && systemId.equals("systemB")) { + /* + * Explicitly set the encoding here or else the parser will + * try to use the parent parser's encoding which is utf-16. + */ + InputSource inputSource = new InputSource( + new ByteArrayInputStream("bob".getBytes("utf-8"))); + inputSource.setEncoding("utf-8"); + return inputSource; + } + + throw new AssertionError(); + } + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + elementNames.add(localName); + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException { + elementNames.add("/" + localName); + } + + @Override + public void characters(char ch[], int start, int length) + throws SAXException { + text.append(ch, start, length); + } + } + + Reader in = new StringReader("<?xml version=\"1.0\"?>\n" + + "<!DOCTYPE foo [\n" + + " <!ENTITY a PUBLIC 'publicA' 'systemA'>\n" + + " <!ENTITY b PUBLIC 'publicB' 'systemB'>\n" + + "]>\n" + + "<foo>\n" + + " &a;<b>&b;</b></foo>"); + + ExpatReader reader = new ExpatReader(); + Handler handler = new Handler(); + reader.setContentHandler(handler); + reader.setEntityResolver(handler); + + reader.parse(new InputSource(in)); + + assertEquals(Arrays.asList("foo", "a", "/a", "b", "/b", "/foo"), + handler.elementNames); + assertEquals("bob", handler.text.toString().trim()); + } + + public void testExternalEntityDownload() throws IOException, SAXException { + class Server implements Runnable { + + private final ServerSocket serverSocket; + + Server() throws IOException { + serverSocket = new ServerSocket(8080); + } + + public void run() { + try { + Socket socket = serverSocket.accept(); + + final InputStream in = socket.getInputStream(); + Thread inputThread = new Thread() { + public void run() { + try { + byte[] buffer = new byte[1024]; + while (in.read(buffer) > -1) { /* ignore */ } + } catch (IOException e) { + e.printStackTrace(); + } + } + }; + inputThread.setDaemon(true); + inputThread.start(); + + OutputStream out = socket.getOutputStream(); + + String body = "<bar></bar>"; + String response = "HTTP/1.0 200 OK\n" + + "Content-Length: " + body.length() + "\n" + + "\n" + + body; + + out.write(response.getBytes("UTF-8")); + out.close(); + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + class Handler extends DefaultHandler { + + List<String> elementNames = new ArrayList<String>(); + + public InputSource resolveEntity(String publicId, String systemId) + throws IOException, SAXException { + // The parser should have resolved the systemId. + assertEquals("http://localhost:8080/systemBar", systemId); + return new InputSource(systemId); + } + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + elementNames.add(localName); + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException { + elementNames.add("/" + localName); + } + } + + // Start server to serve up the XML for 'systemBar'. + Thread serverThread = new Thread(new Server()); + serverThread.setDaemon(true); + serverThread.start(); + + // 'systemBar', the external entity, is relative to 'systemFoo': + Reader in = new StringReader("<?xml version=\"1.0\"?>\n" + + "<!DOCTYPE foo [\n" + + " <!ENTITY bar SYSTEM 'systemBar'>\n" + + "]>\n" + + "<foo>&bar;</foo>"); + + ExpatReader reader = new ExpatReader(); + + Handler handler = new Handler(); + + reader.setContentHandler(handler); + reader.setEntityResolver(handler); + + InputSource source = new InputSource(in); + source.setSystemId("http://localhost:8080/systemFoo"); + reader.parse(source); + + assertEquals(Arrays.asList("foo", "bar", "/bar", "/foo"), + handler.elementNames); + } + + /** + * Parses the given xml string and fires events on the given SAX handler. + */ + private static void parse(String xml, ContentHandler contentHandler) + throws SAXException { + try { + XMLReader reader = new ExpatReader(); + reader.setContentHandler(contentHandler); + reader.parse(new InputSource(new StringReader(xml))); + } + catch (IOException e) { + throw new AssertionError(e); + } + } + + /** + * Parses xml from the given reader and fires events on the given SAX + * handler. + */ + private static void parse(Reader in, ContentHandler contentHandler) + throws IOException, SAXException { + XMLReader reader = new ExpatReader(); + reader.setContentHandler(contentHandler); + reader.parse(new InputSource(in)); + } + + /** + * Parses xml from the given input stream and fires events on the given SAX + * handler. + */ + private static void parse(InputStream in, Encoding encoding, + ContentHandler contentHandler) throws IOException, SAXException { + try { + XMLReader reader = new ExpatReader(); + reader.setContentHandler(contentHandler); + InputSource source = new InputSource(in); + source.setEncoding(encoding.expatName); + reader.parse(source); + } catch (IOException e) { + throw new AssertionError(e); + } + } + + /** + * Supported character encodings. + */ + private enum Encoding { + + US_ASCII("US-ASCII"), + UTF_8("UTF-8"), + UTF_16("UTF-16"), + ISO_8859_1("ISO-8859-1"); + + final String expatName; + + Encoding(String expatName) { + this.expatName = expatName; + } + } + + /** + * Creates a new pull parser with namespace support. + */ + private static XmlPullParser newPullParser() { + ExpatPullParser parser = new ExpatPullParser(); + parser.setNamespaceProcessingEnabled(true); + return parser; + } +} diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/AllTests.java b/xml/src/test/java/tests/api/javax/xml/parsers/AllTests.java new file mode 100644 index 0000000..f0e8ebd --- /dev/null +++ b/xml/src/test/java/tests/api/javax/xml/parsers/AllTests.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.javax.xml.parsers; + +import junit.framework.Test; +import junit.framework.TestSuite; +import org.apache.harmony.xml.ExpatParserTest; + +/** + * This is autogenerated source file. Includes tests for package tests.api.javax.xml.parsers; + */ + +public class AllTests { + + public static void main(String[] args) { + junit.textui.TestRunner.run(AllTests.suite()); + } + + public static Test suite() { + TestSuite suite = tests.TestSuiteFactory.createTestSuite("All tests for package tests.api.javax.xml.parsers;"); + // $JUnit-BEGIN$ + + suite.addTestSuite(DocumentBuilderFactoryTest.class); + suite.addTestSuite(DocumentBuilderTest.class); + suite.addTestSuite(FactoryConfigurationErrorTest.class); + suite.addTestSuite(ParserConfigurationExceptionTest.class); + suite.addTestSuite(SAXParserFactoryTest.class); + suite.addTestSuite(SAXParserTest.class); + suite.addTestSuite(ExpatParserTest.class); + + // $JUnit-END$ + return suite; + } +} diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java new file mode 100644 index 0000000..1e1ffdd --- /dev/null +++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java @@ -0,0 +1,1121 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tests.api.javax.xml.parsers; + +import dalvik.annotation.KnownFailure; +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import junit.framework.TestCase; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import tests.api.javax.xml.parsers.SAXParserFactoryTest.MyHandler; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; + +@TestTargetClass(DocumentBuilderFactory.class) +public class DocumentBuilderFactoryTest extends TestCase { + + DocumentBuilderFactory dbf; + + List<String> cdataElements; + + List<String> textElements; + + List<String> commentElements; + + protected void setUp() throws Exception { + super.setUp(); + dbf = DocumentBuilderFactory.newInstance(); + + cdataElements = new ArrayList<String>(); + textElements = new ArrayList<String>(); + commentElements = new ArrayList<String>(); + } + + protected void tearDown() throws Exception { + dbf = null; + cdataElements = null; + textElements = null; + commentElements = null; + super.tearDown(); + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#DocumentBuilderFactory(). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "DocumentBuilderFactory", + args = {} + ) + public void test_Constructor() { + try { + new DocumentBuilderFactoryChild(); + } catch (Exception e) { + fail("Unexpected exception " + e.toString()); + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#getAttribute(String). + */ +// public void test_getAttributeLjava_lang_String() { +// String[] attributes = { +// "http://java.sun.com/xml/jaxp/properties/schemaLanguage", +// "http://java.sun.com/xml/jaxp/properties/schemaSource" }; +// Object[] values = { "http://www.w3.org/2001/XMLSchema", "source" }; +// +// try { +// for (int i = 0; i < attributes.length; i++) { +// dbf.setAttribute(attributes[i], values[i]); +// assertEquals(values[i], dbf.getAttribute(attributes[i])); +// } +// } catch (IllegalArgumentException e) { +// fail("Unexpected IllegalArgumentException" + e.getMessage()); +// } catch (Exception e) { +// fail("Unexpected exception" + e.getMessage()); +// } +// +// try { +// for (int i = 0; i < attributes.length; i++) { +// dbf.setAttribute(null, null); +// fail("NullPointerException expected"); +// } +// } catch (NullPointerException e) { +// // expected +// } +// +// String[] badAttributes = {"bad1", "bad2", ""}; +// try { +// for (int i = 0; i < badAttributes.length; i++) { +// dbf.getAttribute(badAttributes[i]); +// fail("IllegalArgumentException expected"); +// } +// } catch (IllegalArgumentException e) { +// // expected +// } +// } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#getFeature(String). + */ +// TODO Fails on JDK. Why? +// public void test_getFeatureLjava_lang_String() { +// String[] features = { "http://xml.org/sax/features/namespaces", +// "http://xml.org/sax/features/validation", +// "http://xml.org/sax/features/external-general-entities" }; +// try { +// for (int i = 0; i < features.length; i++) { +// dbf.setFeature(features[i], true); +// assertTrue(dbf.getFeature(features[i])); +// } +// } catch (ParserConfigurationException e) { +// fail("Unexpected ParserConfigurationException " + e.getMessage()); +// } +// +// try { +// for (int i = 0; i < features.length; i++) { +// dbf.setFeature(features[i], false); +// assertFalse(dbf.getFeature(features[i])); +// } +// } catch (ParserConfigurationException e) { +// fail("Unexpected ParserConfigurationException " + e.getMessage()); +// } +// +// try { +// for (int i = 0; i < features.length; i++) { +// dbf.setFeature(null, false); +// fail("NullPointerException expected"); +// } +// } catch (NullPointerException e) { +// // expected +// } catch (ParserConfigurationException e) { +// fail("Unexpected ParserConfigurationException" + e.getMessage()); +// } +// +// String[] badFeatures = {"bad1", "bad2", ""}; +// try { +// for (int i = 0; i < badFeatures.length; i++) { +// dbf.getFeature(badFeatures[i]); +// fail("ParserConfigurationException expected"); +// } +// } catch (ParserConfigurationException e) { +// // expected +// } +// +// } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#getSchema(). + * TBD getSchemas() IS NOT SUPPORTED + */ +/* public void test_getSchema() { + assertNull(dbf.getSchema()); + SchemaFactory sf = + SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + Schema schema = sf.newSchema(); + dbf.setSchema(schema); + assertNotNull(dbf.getSchema()); + } catch (SAXException sax) { + fail("Unexpected exception " + sax.toString()); + } + } + */ + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#isCoalescing(). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isCoalescing", + args = {} + ) + public void test_isCoalescing() { + dbf.setCoalescing(true); + assertTrue(dbf.isCoalescing()); + + dbf.setCoalescing(false); + assertFalse(dbf.isCoalescing()); + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#isExpandEntityReferences(). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isExpandEntityReferences", + args = {} + ) + public void test_isExpandEntityReferences() { + dbf.setExpandEntityReferences(true); + assertTrue(dbf.isExpandEntityReferences()); + + dbf.setExpandEntityReferences(false); + assertFalse(dbf.isExpandEntityReferences()); + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#isIgnoringComments(). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isIgnoringComments", + args = {} + ) + public void test_isIgnoringComments() { + dbf.setIgnoringComments(true); + assertTrue(dbf.isIgnoringComments()); + + dbf.setIgnoringComments(false); + assertFalse(dbf.isIgnoringComments()); + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#isIgnoringElementContentWhitespace(). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isIgnoringElementContentWhitespace", + args = {} + ) + public void test_isIgnoringElementContentWhitespace() { + dbf.setIgnoringElementContentWhitespace(true); + assertTrue(dbf.isIgnoringElementContentWhitespace()); + + dbf.setIgnoringElementContentWhitespace(false); + assertFalse(dbf.isIgnoringElementContentWhitespace()); + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#isNamespaceAware(). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isNamespaceAware", + args = {} + ) + public void test_isNamespaceAware() { + dbf.setNamespaceAware(true); + assertTrue(dbf.isNamespaceAware()); + + dbf.setNamespaceAware(false); + assertFalse(dbf.isNamespaceAware()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isValidating", + args = {} + ), + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "", + method = "setValidating", + args = {boolean.class} + ) + }) + public void test_setIsValidating() { + dbf.setValidating(true); + assertTrue(dbf.isValidating()); + + dbf.setValidating(false); + assertFalse(dbf.isValidating()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isXIncludeAware", + args = {} + ), + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "", + method = "setXIncludeAware", + args = {boolean.class} + ) + }) + @KnownFailure("Should handle XIncludeAware flag more gracefully") + public void test_isSetXIncludeAware() { + dbf.setXIncludeAware(true); + assertTrue(dbf.isXIncludeAware()); + + dbf.setXIncludeAware(false); + assertFalse(dbf.isXIncludeAware()); + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#newInstance(). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "newInstance", + args = {} + ) + public void test_newInstance() { + String className = null; + try { + // case 1: Try to obtain a new instance of factory by default. + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + assertNotNull(dbf); + + // case 2: Try to create a new instance of factory using + // property DATATYPEFACTORY_PROPERTY + className = System.getProperty("javax.xml.parsers.DocumentBuilderFactory"); + System.setProperty("javax.xml.parsers.DocumentBuilderFactory", + "org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl"); + + dbf = DocumentBuilderFactory.newInstance(); + assertNotNull(dbf); + assertTrue(dbf instanceof org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl); + + // case 3: Try to create a new instance of factory using Property + String keyValuePair = "javax.xml.parsers.DocumentBuilderFactory" + + "=" + "org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl"; + ByteArrayInputStream bis = new ByteArrayInputStream(keyValuePair + .getBytes()); + Properties prop = System.getProperties(); + prop.load(bis); + dbf = DocumentBuilderFactory.newInstance(); + assertNotNull(dbf); + assertTrue(dbf instanceof org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl); + + // case 4: Check FactoryConfiguration error + System.setProperty("javax.xml.parsers.DocumentBuilderFactory", ""); + try { + DocumentBuilderFactory.newInstance(); + } catch (FactoryConfigurationError fce) { + // expected + } + + } catch (Exception e) { + fail("Unexpected exception " + e.toString()); + } finally { + // Set default value of Datatype factory, + // because of this test modifies it. + if (className == null) { + System.clearProperty("javax.xml.parsers.DocumentBuilderFactory"); + } else { + System.setProperty("javax.xml.parsers.DocumentBuilderFactory", + className); + } + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "SAXException untested; unused on Android", + method = "newDocumentBuilder", + args = {} + ) + public void test_newDocumentBuilder() { + // Ordinary case + try { + DocumentBuilder db = dbf.newDocumentBuilder(); + assertTrue(db instanceof DocumentBuilder); + db.parse(getClass().getResourceAsStream("/simple.xml")); + } catch(Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Exception case + dbf.setValidating(true); + try { + DocumentBuilder db = dbf.newDocumentBuilder(); + } catch(ParserConfigurationException e) { + // Expected, since Android doesn't have a validating parser. + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setAttribute(java.lang.String, + * java.lang.Object). + */ +// public void test_setAttributeLjava_lang_StringLjava_lang_Object() { +// String[] attributes = { +// "http://java.sun.com/xml/jaxp/properties/schemaLanguage", +// "http://java.sun.com/xml/jaxp/properties/schemaSource" }; +// Object[] values = { "http://www.w3.org/2001/XMLSchema", "source" }; +// +// try { +// for (int i = 0; i < attributes.length; i++) { +// dbf.setAttribute(attributes[i], values[i]); +// assertEquals(values[i], dbf.getAttribute(attributes[i])); +// } +// } catch (IllegalArgumentException e) { +// fail("Unexpected IllegalArgumentException" + e.getMessage()); +// } catch (Exception e) { +// fail("Unexpected exception" + e.getMessage()); +// } +// +// String[] badAttributes = {"bad1", "bad2", ""}; +// try { +// for (int i = 0; i < badAttributes.length; i++) { +// dbf.setAttribute(badAttributes[i], ""); +// fail("IllegalArgumentException expected"); +// } +// } catch (IllegalArgumentException iae) { +// // expected +// } +// +// try { +// for (int i = 0; i < attributes.length; i++) { +// dbf.setAttribute(null, null); +// fail("NullPointerException expected"); +// } +// } catch (NullPointerException e) { +// // expected +// } +// } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setCoalescing(boolean). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "setCoalescing", + args = {boolean.class} + ) + @KnownFailure("Should support coalescing") + public void test_setCoalescingZ() { + dbf.setCoalescing(true); + assertTrue(dbf.isCoalescing()); + + textElements.clear(); + cdataElements.clear(); + Exception parseException = null; + DocumentBuilder parser = null; + + try { + parser = dbf.newDocumentBuilder(); + ValidationErrorHandler errorHandler = new ValidationErrorHandler(); + parser.setErrorHandler(errorHandler); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + parseException = errorHandler.getFirstException(); + + goThroughDocument((Node) document, ""); + assertTrue(textElements + .contains("BeefParmesan<title>withGarlicAngelHairPasta</title>")); + } catch (Exception ex) { + parseException = ex; + } + parser.setErrorHandler(null); + + if (parseException != null) { + fail("Unexpected exception " + parseException.getMessage()); + } + + dbf.setCoalescing(false); + assertFalse(dbf.isCoalescing()); + + textElements.clear(); + cdataElements.clear(); + + try { + parser = dbf.newDocumentBuilder(); + ValidationErrorHandler errorHandler = new ValidationErrorHandler(); + parser.setErrorHandler(errorHandler); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + parseException = errorHandler.getFirstException(); + + goThroughDocument((Node) document, ""); + + assertFalse(textElements + .contains("BeefParmesan<title>withGarlicAngelHairPasta</title>")); + + } catch (Exception ex) { + parseException = ex; + } + parser.setErrorHandler(null); + + if (parseException != null) { + fail("Unexpected exception " + parseException.getMessage()); + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setExpandEntityReferences(boolean). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "setExpandEntityReferences", + args = {boolean.class} + ) + public void test_setExpandEntityReferencesZ() { + dbf.setExpandEntityReferences(true); + assertTrue(dbf.isExpandEntityReferences()); + + Exception parseException = null; + DocumentBuilder parser = null; + + try { + parser = dbf.newDocumentBuilder(); + ValidationErrorHandler errorHandler = new ValidationErrorHandler(); + parser.setErrorHandler(errorHandler); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + parseException = errorHandler.getFirstException(); + + assertNotNull(document); + + } catch (Exception ex) { + parseException = ex; + } + parser.setErrorHandler(null); + + if (parseException != null) { + fail("Unexpected exception " + parseException.getMessage()); + } + + dbf.setExpandEntityReferences(false); + assertFalse(dbf.isExpandEntityReferences()); + try { + parser = dbf.newDocumentBuilder(); + ValidationErrorHandler errorHandler = new ValidationErrorHandler(); + parser.setErrorHandler(errorHandler); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + parseException = errorHandler.getFirstException(); + + assertNotNull(document); + + } catch (Exception ex) { + parseException = ex; + } + parser.setErrorHandler(null); + + if (parseException != null) { + fail("Unexpected exception " + parseException.getMessage()); + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setFeature(java.lang.String). + */ + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getFeature", + args = {java.lang.String.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "setFeature", + args = {java.lang.String.class, boolean.class} + ) + }) + public void test_getSetFeatureLjava_lang_String() { + String[] features = { "http://xml.org/sax/features/namespaces", + "http://xml.org/sax/features/validation" }; + try { + for (int i = 0; i < features.length; i++) { + dbf.setFeature(features[i], true); + assertTrue(dbf.getFeature(features[i])); + } + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException" + e.getMessage()); + } + + try { + for (int i = 0; i < features.length; i++) { + dbf.setFeature(features[i], false); + assertFalse(dbf.getFeature(features[i])); + } + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException" + e.getMessage()); + } + + try { + for (int i = 0; i < features.length; i++) { + dbf.setFeature(null, false); + fail("NullPointerException expected"); + } + } catch (NullPointerException e) { + // expected + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException" + e.getMessage()); + } + + String[] badFeatures = { "bad1", "bad2", "" }; + try { + for (int i = 0; i < badFeatures.length; i++) { + dbf.setFeature(badFeatures[i], false); + fail("ParserConfigurationException expected"); + } + } catch (ParserConfigurationException e) { + // expected + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setIgnoringComments(boolean). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "setIgnoringComments", + args = {boolean.class} + ) + public void test_setIgnoringCommentsZ() { + commentElements.clear(); + + dbf.setIgnoringComments(true); + assertTrue(dbf.isIgnoringComments()); + + try { + DocumentBuilder parser = dbf.newDocumentBuilder(); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + goThroughDocument((Node) document, ""); + assertFalse(commentElements.contains("comment1")); + assertFalse(commentElements.contains("comment2")); + + } catch (IOException e) { + fail("Unexpected IOException " + e.getMessage()); + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException " + e.getMessage()); + } catch (SAXException e) { + fail("Unexpected SAXException " + e.getMessage()); + } + + commentElements.clear(); + + dbf.setIgnoringComments(false); + assertFalse(dbf.isIgnoringComments()); + + try { + DocumentBuilder parser = dbf.newDocumentBuilder(); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + goThroughDocument((Node) document, ""); + assertTrue(commentElements.contains("comment1")); + assertTrue(commentElements.contains("comment2")); + + } catch (IOException e) { + fail("Unexpected IOException " + e.getMessage()); + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException " + e.getMessage()); + } catch (SAXException e) { + fail("Unexpected SAXException " + e.getMessage()); + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setIgnoringElementContentWhitespace(boolean). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "setIgnoringElementContentWhitespace", + args = {boolean.class} + ) + public void test_setIgnoringElementContentWhitespaceZ() { + dbf.setIgnoringElementContentWhitespace(true); + assertTrue(dbf.isIgnoringElementContentWhitespace()); + + try { + DocumentBuilder parser = dbf.newDocumentBuilder(); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + assertNotNull(document); + + } catch (IOException e) { + fail("Unexpected IOException " + e.getMessage()); + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException " + e.getMessage()); + } catch (SAXException e) { + fail("Unexpected SAXException " + e.getMessage()); + } + + dbf.setIgnoringElementContentWhitespace(false); + assertFalse(dbf.isIgnoringElementContentWhitespace()); + + try { + DocumentBuilder parser = dbf.newDocumentBuilder(); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + assertNotNull(document); + + } catch (IOException e) { + fail("Unexpected IOException " + e.getMessage()); + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException " + e.getMessage()); + } catch (SAXException e) { + fail("Unexpected SAXException " + e.getMessage()); + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setNamespaceAware(boolean). + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "setNamespaceAware", + args = {boolean.class} + ) + public void test_setNamespaceAwareZ() { + dbf.setNamespaceAware(true); + assertTrue(dbf.isNamespaceAware()); + + try { + DocumentBuilder parser = dbf.newDocumentBuilder(); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + assertNotNull(document); + + } catch (IOException e) { + fail("Unexpected IOException " + e.getMessage()); + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException " + e.getMessage()); + } catch (SAXException e) { + fail("Unexpected SAXException " + e.getMessage()); + } + + dbf.setNamespaceAware(false); + assertFalse(dbf.isNamespaceAware()); + + try { + DocumentBuilder parser = dbf.newDocumentBuilder(); + + Document document = parser.parse(getClass().getResourceAsStream( + "/recipt.xml")); + + assertNotNull(document); + + } catch (IOException e) { + fail("Unexpected IOException " + e.getMessage()); + } catch (ParserConfigurationException e) { + fail("Unexpected ParserConfigurationException " + e.getMessage()); + } catch (SAXException e) { + fail("Unexpected SAXException " + e.getMessage()); + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getAttribute", + args = {java.lang.String.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "setAttribute", + args = {java.lang.String.class, Object.class} + ) + }) + public void test_getSetAttribute() { + // Android SAX implementation doesn't support attributes, so + // we can only make sure the expected exception is thrown. + try { + dbf.setAttribute("foo", new Object()); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // Expected + } + + try { + dbf.getAttribute("foo"); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setSchema(javax.xml.validation.Schema). + */ + /* public void test_setSchemaLjavax_xml_validation_Schema() { + SchemaFactory sf = + SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + Schema schema = sf.newSchema(); + dbf.setSchema(schema); + assertNotNull(dbf.getSchema()); + } catch (SAXException sax) { + fail("Unexpected exception " + sax.toString()); + } + } +*/ + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setValidating(boolean). + */ +// public void test_setValidatingZ() { +// Exception parseException = null; +// DocumentBuilder parser = null; +// Document document = null; +// +// ValidationErrorHandler errorHandler = new ValidationErrorHandler(); +// +// dbf.setValidating(false); +// assertFalse(dbf.isValidating()); +// +// // case 1: Validation is not set. Correct xml-file +// try { +// +// parser = dbf.newDocumentBuilder(); +// parser.setErrorHandler(errorHandler); +// +// document = parser.parse(getClass().getResourceAsStream( +// "/recipt.xml")); +// +// parseException = errorHandler.getFirstException(); +// +// assertNotNull(document); +// +// document = parser.parse(getClass().getResourceAsStream( +// "/reciptWrong.xml")); +// +// parseException = errorHandler.getFirstException(); +// +// assertNotNull(document); +// +// } catch (Exception ex) { +// parseException = ex; +// } +// parser.setErrorHandler(null); +// +// if (parseException != null) { +// fail("Unexpected exception " + parseException.getMessage()); +// } +// +// // case 2: Validation is not set. Wrong xml-file +// try { +// +// parser = dbf.newDocumentBuilder(); +// parser.setErrorHandler(errorHandler); +// +// document = parser.parse(getClass().getResourceAsStream( +// "/reciptWrong.xml")); +// parseException = errorHandler.getFirstException(); +// +// assertNotNull(document); +// +// } catch (Exception ex) { +// parseException = ex; +// } +// parser.setErrorHandler(null); +// +// if (parseException != null) { +// fail("Unexpected exception " + parseException.getMessage()); +// } +// +// // case 3: Validation is set. Correct xml-file +// dbf.setValidating(true); +// assertTrue(dbf.isValidating()); +// +// try { +// +// parser = dbf.newDocumentBuilder(); +// parser.setErrorHandler(errorHandler); +// +// document = parser.parse(getClass().getResourceAsStream( +// "/recipt.xml")); +// parseException = errorHandler.getFirstException(); +// +// assertNotNull(document); +// +// } catch (Exception ex) { +// parseException = ex; +// } +// parser.setErrorHandler(null); +// +// if (parseException != null) { +// fail("Unexpected exception " + parseException.getMessage()); +// } +// +// // case 4: Validation is set. Wrong xml-file +// try { +// +// parser = dbf.newDocumentBuilder(); +// parser.setErrorHandler(errorHandler); +// +// document = parser.parse(getClass().getResourceAsStream( +// "/reciptWrong.xml")); +// parseException = errorHandler.getFirstException(); +// +// assertNotNull(document); +// +// } catch (Exception ex) { +// parseException = ex; +// } +// parser.setErrorHandler(null); +// +// if (parseException == null) { +// fail("Unexpected exception " + parseException.getMessage()); +// } else { +// assertTrue(parseException +// .getMessage() +// .contains( +// "The content of element type \"collection\" must match \"(description,recipe+)\"")); +// } +// +// } + + /** + * @tests javax.xml.parsers.DocumentBuilderFactory#setXIncludeAware(). + */ +// public void test_setXIncludeAware() { +// dbf.setXIncludeAware(true); +// assertTrue(dbf.isXIncludeAware()); +// +// try { +// DocumentBuilder parser = dbf.newDocumentBuilder(); +// +// Document document = parser.parse(getClass().getResourceAsStream( +// "/recipt.xml")); +// +// assertNotNull(document); +// +// } catch (IOException e) { +// fail("Unexpected IOException " + e.getMessage()); +// } catch (ParserConfigurationException e) { +// fail("Unexpected ParserConfigurationException " + e.getMessage()); +// } catch (SAXException e) { +// fail("Unexpected SAXException " + e.getMessage()); +// } +// +// dbf.setXIncludeAware(false); +// assertFalse(dbf.isXIncludeAware()); +// +// try { +// DocumentBuilder parser = dbf.newDocumentBuilder(); +// +// Document document = parser.parse(getClass().getResourceAsStream( +// "/recipt.xml")); +// +// assertNotNull(document); +// +// } catch (IOException e) { +// fail("Unexpected IOException " + e.getMessage()); +// } catch (ParserConfigurationException e) { +// fail("Unexpected ParserConfigurationException " + e.getMessage()); +// } catch (SAXException e) { +// fail("Unexpected SAXException " + e.getMessage()); +// } +// } + + private void goThroughDocument(Node node, String indent) { + String value = node.getNodeValue(); + + if (value != null) { + value = value.replaceAll(" ", ""); + value = value.replaceAll("\n", ""); + } + + switch (node.getNodeType()) { + case Node.CDATA_SECTION_NODE: + cdataElements.add(value); + // System.out.println(indent + "CDATA_SECTION_NODE " + value); + break; + case Node.COMMENT_NODE: + commentElements.add(value); + // System.out.println(indent + "COMMENT_NODE " + value); + break; + case Node.DOCUMENT_FRAGMENT_NODE: + // System.out.println(indent + "DOCUMENT_FRAGMENT_NODE " + value); + break; + case Node.DOCUMENT_NODE: + // System.out.println(indent + "DOCUMENT_NODE " + value); + break; + case Node.DOCUMENT_TYPE_NODE: + // System.out.println(indent + "DOCUMENT_TYPE_NODE " + value); + break; + case Node.ELEMENT_NODE: + // System.out.println(indent + "ELEMENT_NODE " + value); + break; + case Node.ENTITY_NODE: + // System.out.println(indent + "ENTITY_NODE " + value); + break; + case Node.ENTITY_REFERENCE_NODE: + // System.out.println(indent + "ENTITY_REFERENCE_NODE " + value); + break; + case Node.NOTATION_NODE: + // System.out.println(indent + "NOTATION_NODE " + value); + break; + case Node.PROCESSING_INSTRUCTION_NODE: + // System.out.println(indent + "PROCESSING_INSTRUCTION_NODE " + + // value); + break; + case Node.TEXT_NODE: + textElements.add(value); + // System.out.println(indent + "TEXT_NODE " + value); + break; + default: + // System.out.println(indent + "Unknown node " + value); + break; + } + NodeList list = node.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) + goThroughDocument(list.item(i), indent + " "); + } + + private class ValidationErrorHandler implements ErrorHandler { + private SAXException parseException; + + private int errorCount; + + private int warningCount; + + public ValidationErrorHandler() { + parseException = null; + errorCount = 0; + warningCount = 0; + } + + public void error(SAXParseException ex) { + errorCount++; + if (parseException == null) { + parseException = ex; + } + } + + public void warning(SAXParseException ex) { + warningCount++; + } + + public void fatalError(SAXParseException ex) { + if (parseException == null) { + parseException = ex; + } + } + + public SAXException getFirstException() { + return parseException; + } + } + + private class DocumentBuilderFactoryChild extends DocumentBuilderFactory { + public DocumentBuilderFactoryChild() { + super(); + } + + public Object getAttribute(String name) { + return null; + } + + public boolean getFeature(String name) { + return false; + } + + public DocumentBuilder newDocumentBuilder() { + return null; + } + + public void setAttribute(String name, Object value) { + } + + public void setFeature(String name, boolean value) { + } + + } +} diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java new file mode 100644 index 0000000..181e8f5 --- /dev/null +++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java @@ -0,0 +1,733 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.javax.xml.parsers; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import junit.framework.TestCase; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.EntityReference; +import org.w3c.dom.Text; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import tests.api.org.xml.sax.support.MethodLogger; +import tests.api.org.xml.sax.support.MockHandler; +import tests.api.org.xml.sax.support.MockResolver; +import dalvik.annotation.BrokenTest; +import dalvik.annotation.KnownFailure; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@TestTargetClass(DocumentBuilder.class) +public class DocumentBuilderTest extends TestCase { + + private class MockDocumentBuilder extends DocumentBuilder { + + public MockDocumentBuilder() { + super(); + } + + /* + * @see javax.xml.parsers.DocumentBuilder#getDOMImplementation() + */ + @Override + public DOMImplementation getDOMImplementation() { + // it is a fake + return null; + } + + /* + * @see javax.xml.parsers.DocumentBuilder#isNamespaceAware() + */ + @Override + public boolean isNamespaceAware() { + // it is a fake + return false; + } + + /* + * @see javax.xml.parsers.DocumentBuilder#isValidating() + */ + @Override + public boolean isValidating() { + // it is a fake + return false; + } + + /* + * @see javax.xml.parsers.DocumentBuilder#newDocument() + */ + @Override + public Document newDocument() { + // it is a fake + return null; + } + + /* + * @see javax.xml.parsers.DocumentBuilder#parse(org.xml.sax.InputSource) + */ + @Override + public Document parse(InputSource is) throws SAXException, IOException { + // it is a fake + return null; + } + + /* + * @see javax.xml.parsers.DocumentBuilder#setEntityResolver( + * org.xml.sax.EntityResolver) + */ + @Override + public void setEntityResolver(EntityResolver er) { + // it is a fake + } + + /* + * @see javax.xml.parsers.DocumentBuilder#setErrorHandler( + * org.xml.sax.ErrorHandler) + */ + @Override + public void setErrorHandler(ErrorHandler eh) { + // it is a fake + } + + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + } + + DocumentBuilderFactory dbf; + + DocumentBuilder db; + + protected void setUp() throws Exception { + dbf = DocumentBuilderFactory.newInstance(); + + dbf.setIgnoringElementContentWhitespace(true); + + db = dbf.newDocumentBuilder(); + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "DocumentBuilder", + args = {} + ) + public void testDocumentBuilder() { + try { + new MockDocumentBuilder(); + } catch (Exception e) { + fail("unexpected exception " + e.toString()); + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilder#getSchema() + * TBD getSchema() is not supported + */ + /* public void test_getSchema() { + assertNull(db.getSchema()); + SchemaFactory sf = + SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + Schema schema = sf.newSchema(); + dbf.setSchema(schema); + assertNotNull(dbf.newDocumentBuilder().getSchema()); + } catch (ParserConfigurationException pce) { + fail("Unexpected ParserConfigurationException " + pce.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } +*/ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "newDocument", + args = { } + ) + public void testNewDocument() { + Document d; + + try { + d = dbf.newDocumentBuilder().newDocument(); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertNotNull(d); + assertNull(d.getDoctype()); + assertNull(d.getDocumentElement()); + assertNull(d.getNamespaceURI()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getDOMImplementation", + args = { } + ) + public void testGetImplementation() { + DOMImplementation d; + + try { + d = dbf.newDocumentBuilder().getDOMImplementation(); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertNotNull(d); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isNamespaceAware", + args = {} + ) + public void testIsNamespaceAware() { + try { + dbf.setNamespaceAware(true); + assertTrue(dbf.newDocumentBuilder().isNamespaceAware()); + dbf.setNamespaceAware(false); + assertFalse(dbf.newDocumentBuilder().isNamespaceAware()); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "No validating parser in Android, hence not tested", + method = "isValidating", + args = {} + ) + public void testIsValidating() { + try { + dbf.setValidating(false); + assertFalse(dbf.newDocumentBuilder().isValidating()); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "No XInclude-aware parser in Android, hence not tested", + method = "isXIncludeAware", + args = {} + ) + @KnownFailure("Should handle XIncludeAware flag more gracefully") + public void testIsXIncludeAware() { + try { + dbf.setXIncludeAware(false); + assertFalse(dbf.newDocumentBuilder().isXIncludeAware()); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.File) + * Case 1: Try to parse correct xml document. + * Case 2: Try to call parse() with null argument. + * Case 3: Try to parse a non-existent file. + * Case 4: Try to parse incorrect xml file. + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "parse", + args = {java.io.File.class} + ) + @BrokenTest("Need to use XML file from correct location") + public void test_parseLjava_io_File() { + File f = new File("/tmp/xml_source/simple.xml"); + // case 1: Trivial use. + try { + Document d = db.parse(f); + assertNotNull(d); + // TBD getXmlEncoding() IS NOT SUPPORTED + // assertEquals("ISO-8859-1", d.getXmlEncoding()); + assertEquals(2, d.getChildNodes().getLength()); + assertEquals("#comment", + d.getChildNodes().item(0).getNodeName()); + assertEquals("breakfast_menu", + d.getChildNodes().item(1).getNodeName()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 2: Try to call parse with null argument + try { + db.parse((File)null); + fail("Expected IllegalArgumentException was not thrown"); + } catch (IllegalArgumentException iae) { + // expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 3: Try to parse a non-existent file + try { + db.parse(new File("_")); + fail("Expected IOException was not thrown"); + } catch (IOException ioe) { + // expected + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 4: Try to parse incorrect xml file + try { + f = new File("/tmp/xml_source/wrong.xml"); + db.parse(f); + fail("Expected SAXException was not thrown"); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + // expected + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream) + * Case 1: Try to parse correct xml document. + * Case 2: Try to call parse() with null argument. + * Case 3: Try to parse a non-existent file. + * Case 4: Try to parse incorrect xml file. + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "parse", + args = {java.io.InputStream.class} + ) + public void test_parseLjava_io_InputStream() { + InputStream is = getClass().getResourceAsStream("/simple.xml"); + // case 1: Trivial use. + try { + Document d = db.parse(is); + assertNotNull(d); + // TBD getXmlEncoding() IS NOT SUPPORTED + // assertEquals("ISO-8859-1", d.getXmlEncoding()); + assertEquals(2, d.getChildNodes().getLength()); + assertEquals("#comment", + d.getChildNodes().item(0).getNodeName()); + assertEquals("breakfast_menu", + d.getChildNodes().item(1).getNodeName()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 2: Try to call parse with null argument + try { + db.parse((InputStream)null); + fail("Expected IllegalArgumentException was not thrown"); + } catch (IllegalArgumentException iae) { + // expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 3: Try to parse a non-existent file + try { + db.parse(new FileInputStream("_")); + fail("Expected IOException was not thrown"); + } catch (IOException ioe) { + // expected + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 4: Try to parse incorrect xml file + try { + is = getClass().getResourceAsStream("/wrong.xml"); + db.parse(is); + fail("Expected SAXException was not thrown"); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + // expected + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream) + * Case 1: Try to parse correct xml document. + * Case 2: Try to call parse() with null argument. + * Case 3: Try to parse a non-existent file. + * Case 4: Try to parse incorrect xml file. + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "parse", + args = { InputSource.class } + ) + public void testParseInputSource() { + InputStream stream = getClass().getResourceAsStream("/simple.xml"); + InputSource is = new InputSource(stream); + + // case 1: Trivial use. + try { + Document d = db.parse(is); + assertNotNull(d); + // TBD getXmlEncoding() IS NOT SUPPORTED + // assertEquals("ISO-8859-1", d.getXmlEncoding()); + assertEquals(2, d.getChildNodes().getLength()); + assertEquals("#comment", + d.getChildNodes().item(0).getNodeName()); + assertEquals("breakfast_menu", + d.getChildNodes().item(1).getNodeName()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 2: Try to call parse with null argument + try { + db.parse((InputSource)null); + fail("Expected IllegalArgumentException was not thrown"); + } catch (IllegalArgumentException iae) { + // expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 3: Try to parse a non-existent file + try { + db.parse(new InputSource(new FileInputStream("_"))); + fail("Expected IOException was not thrown"); + } catch (IOException ioe) { + // expected + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 4: Try to parse incorrect xml file + try { + is = new InputSource(getClass().getResourceAsStream("/wrong.xml")); + db.parse(is); + fail("Expected SAXException was not thrown"); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + // expected + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream, + * java.lang.String) + * Case 1: Try to parse correct xml document. + * Case 2: Try to call parse() with null argument. + * Case 3: Try to parse a non-existent file. + * Case 4: Try to parse incorrect xml file. + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "parse", + args = {java.io.InputStream.class, java.lang.String.class} + ) + public void test_parseLjava_io_InputStreamLjava_lang_String() { + InputStream is = getClass().getResourceAsStream("/systemid.xml"); + // case 1: Trivial use. + try { + Document d = db.parse(is, SAXParserTestSupport.XML_SYSTEM_ID); + assertNotNull(d); +// TBD getXmlEncoding() is not supported +// assertEquals("UTF-8", d.getXmlEncoding()); + assertEquals(4, d.getChildNodes().getLength()); + assertEquals("collection", + d.getChildNodes().item(0).getNodeName()); + assertEquals("#comment", + d.getChildNodes().item(1).getNodeName()); + assertEquals("collection", + d.getChildNodes().item(2).getNodeName()); + assertEquals("#comment", + d.getChildNodes().item(3).getNodeName()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 2: Try to call parse with null argument + try { + db.parse((InputStream)null, SAXParserTestSupport.XML_SYSTEM_ID); + fail("Expected IllegalArgumentException was not thrown"); + } catch (IllegalArgumentException iae) { + // expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 3: Try to parse a non-existent file +// Doesn't make sense this way... +// try { +// db.parse(is, "/"); +// fail("Expected IOException was not thrown"); +// } catch (IOException ioe) { +// // expected +// } catch (SAXException sax) { +// fail("Unexpected SAXException " + sax.toString()); +// } + + // case 4: Try to parse incorrect xml file + try { + is = getClass().getResourceAsStream("/wrong.xml"); + db.parse(is, SAXParserTestSupport.XML_SYSTEM_ID); + fail("Expected SAXException was not thrown"); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + // expected + } + } + + /** + * @tests javax.xml.parsers.DocumentBuilder#parse(java.lang.String) + * Case 1: Try to parse correct xml document. + * Case 2: Try to call parse() with null argument. + * Case 3: Try to parse a non-existent uri. + * Case 4: Try to parse incorrect xml file. + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "parse", + args = {java.lang.String.class} + ) + @KnownFailure("Android DocumentBuilder should support File sources") + public void test_parseLjava_lang_String() { + // case 1: Trivial use. + File f = new File(getClass().getResource("/simple.xml").getFile()); + try { + Document d = db.parse(f.getAbsolutePath()); + assertNotNull(d); +// TBD getXmlEncoding() is not supported +// assertEquals("ISO-8859-1", d.getXmlEncoding()); + assertEquals(2, d.getChildNodes().getLength()); + assertEquals("#comment", + d.getChildNodes().item(0).getNodeName()); + assertEquals("breakfast_menu", + d.getChildNodes().item(1).getNodeName()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 2: Try to call parse with null argument + try { + db.parse((String)null); + fail("Expected IllegalArgumentException was not thrown"); + } catch (IllegalArgumentException iae) { + // expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 3: Try to parse a non-existent uri + try { + db.parse("_"); + fail("Expected IOException was not thrown"); + } catch (IOException ioe) { + // expected + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // case 4: Try to parse incorrect xml file + try { + f = new File(getClass().getResource("/wrong.xml").getFile()); + db.parse(f.getAbsolutePath()); + fail("Expected SAXException was not thrown"); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + // expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "reset", + args = { } + ) + @KnownFailure("Android DocumentBuilder should implement reset() properly") + public void testReset() { + // Make sure EntityResolver gets reset + InputStream source = new ByteArrayInputStream("<a>&foo;</a>".getBytes()); + InputStream entity = new ByteArrayInputStream("bar".getBytes()); + + MockResolver resolver = new MockResolver(); + resolver.addEntity("foo", "foo", new InputSource(entity)); + + Document d; + + try { + db = dbf.newDocumentBuilder(); + db.setEntityResolver(resolver); + db.reset(); + d = db.parse(source); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + Element root = (Element)d.getElementsByTagName("a").item(0); + assertEquals("foo", ((EntityReference)root.getFirstChild()).getNodeName()); + + // Make sure ErrorHandler gets reset + source = new ByteArrayInputStream("</a>".getBytes()); + + MethodLogger logger = new MethodLogger(); + ErrorHandler handler = new MockHandler(logger); + + try { + db = dbf.newDocumentBuilder(); + db.setErrorHandler(handler); + db.reset(); + d = db.parse(source); + } catch (SAXParseException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(0, logger.size()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setErrorHandler", + args = { ErrorHandler.class } + ) + public void testSetErrorHandler() { + // Ordinary case + InputStream source = new ByteArrayInputStream("</a>".getBytes()); + + MethodLogger logger = new MethodLogger(); + ErrorHandler handler = new MockHandler(logger); + + try { + db = dbf.newDocumentBuilder(); + db.setErrorHandler(handler); + db.parse(source); + } catch (SAXParseException e) { + // Expected, ErrorHandler does not mask exception + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals("error", logger.getMethod()); + assertTrue(logger.getArgs()[0] instanceof SAXParseException); + + // null case + source = new ByteArrayInputStream("</a>".getBytes()); + + try { + db = dbf.newDocumentBuilder(); + db.setErrorHandler(null); + db.parse(source); + } catch (SAXParseException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setEntityResolver", + args = { EntityResolver.class } + ) + @KnownFailure("Android DocumentBuilder should support entity resolving") + public void testSetEntityResolver() { + // Ordinary case + InputStream source = new ByteArrayInputStream("<a>&foo;</a>".getBytes()); + InputStream entity = new ByteArrayInputStream("bar".getBytes()); + + MockResolver resolver = new MockResolver(); + resolver.addEntity("foo", "foo", new InputSource(entity)); + + Document d; + + try { + db = dbf.newDocumentBuilder(); + db.setEntityResolver(resolver); + d = db.parse(source); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + Element root = (Element)d.getElementsByTagName("a").item(0); + assertEquals("bar", ((Text)root.getFirstChild()).getData()); + + // null case + source = new ByteArrayInputStream("<a>&foo;</a>".getBytes()); + + try { + db = dbf.newDocumentBuilder(); + db.setEntityResolver(null); + d = db.parse(source); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + root = (Element)d.getElementsByTagName("a").item(0); + assertEquals("foo", ((EntityReference)root.getFirstChild()).getNodeName()); + } + +} diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/FactoryConfigurationErrorTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/FactoryConfigurationErrorTest.java new file mode 100644 index 0000000..0b5f230 --- /dev/null +++ b/xml/src/test/java/tests/api/javax/xml/parsers/FactoryConfigurationErrorTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tests.api.javax.xml.parsers; + +import javax.xml.parsers.FactoryConfigurationError; + +import junit.framework.TestCase; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@TestTargetClass(FactoryConfigurationError.class) +public class FactoryConfigurationErrorTest extends TestCase { + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "FactoryConfigurationError", + args = {} + ) + public void test_Constructor() { + FactoryConfigurationError fce = new FactoryConfigurationError(); + assertNull(fce.getMessage()); + assertNull(fce.getLocalizedMessage()); + assertNull(fce.getCause()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "FactoryConfigurationError", + args = {java.lang.Exception.class} + ) + public void test_ConstructorLjava_lang_Exception() { + Exception e = new Exception(); + // case 1: Try to create FactoryConfigurationError + // which is based on Exception without parameters. + FactoryConfigurationError fce = new FactoryConfigurationError(e); + assertNotNull(fce.getMessage()); + assertNotNull(fce.getLocalizedMessage()); + assertEquals(e.getCause(), fce.getCause()); + + // case 2: Try to create FactoryConfigurationError + // which is based on Exception with String parameter. + e = new Exception("test message"); + fce = new FactoryConfigurationError(e); + assertEquals(e.toString(), fce.getMessage()); + assertEquals(e.toString(), fce.getLocalizedMessage()); + assertEquals(e.getCause(), fce.getCause()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "FactoryConfigurationError", + args = {java.lang.Exception.class, java.lang.String.class} + ) + public void test_ConstructorLjava_lang_ExceptionLjava_lang_String() { + Exception e = new Exception(); + // case 1: Try to create FactoryConfigurationError + // which is based on Exception without parameters. + FactoryConfigurationError fce = new FactoryConfigurationError(e, "msg"); + assertNotNull(fce.getMessage()); + assertNotNull(fce.getLocalizedMessage()); + assertEquals(e.getCause(), fce.getCause()); + + // case 2: Try to create FactoryConfigurationError + // which is based on Exception with String parameter. + e = new Exception("test message"); + fce = new FactoryConfigurationError(e, "msg"); + assertEquals("msg", fce.getMessage()); + assertEquals("msg", fce.getLocalizedMessage()); + assertEquals(e.getCause(), fce.getCause()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "FactoryConfigurationError", + args = {java.lang.String.class} + ) + public void test_ConstructorLjava_lang_String() { + FactoryConfigurationError fce = new FactoryConfigurationError("Oops!"); + assertEquals("Oops!", fce.getMessage()); + assertEquals("Oops!", fce.getLocalizedMessage()); + assertNull(fce.getCause()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getException", + args = {} + ) + public void test_getException() { + FactoryConfigurationError fce = new FactoryConfigurationError(); + assertNull(fce.getException()); + fce = new FactoryConfigurationError("test"); + assertNull(fce.getException()); + Exception e = new Exception("msg"); + fce = new FactoryConfigurationError(e); + assertEquals(e, fce.getException()); + NullPointerException npe = new NullPointerException(); + fce = new FactoryConfigurationError(npe); + assertEquals(npe, fce.getException()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getMessage", + args = {} + ) + public void test_getMessage() { + assertNull(new FactoryConfigurationError().getMessage()); + assertEquals("msg1", + new FactoryConfigurationError("msg1").getMessage()); + assertEquals(new Exception("msg2").toString(), + new FactoryConfigurationError( + new Exception("msg2")).getMessage()); + assertEquals(new NullPointerException().toString(), + new FactoryConfigurationError( + new NullPointerException()).getMessage()); + } + +} diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/ParserConfigurationExceptionTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/ParserConfigurationExceptionTest.java new file mode 100644 index 0000000..63b87a7 --- /dev/null +++ b/xml/src/test/java/tests/api/javax/xml/parsers/ParserConfigurationExceptionTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tests.api.javax.xml.parsers; + +import javax.xml.parsers.ParserConfigurationException; + +import junit.framework.TestCase; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@TestTargetClass(ParserConfigurationException.class) +public class ParserConfigurationExceptionTest extends TestCase{ + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "ParserConfigurationException", + args = {} + ) + public void test_Constructor() { + ParserConfigurationException pce = new ParserConfigurationException(); + assertNull(pce.getMessage()); + assertNull(pce.getLocalizedMessage()); + assertNull(pce.getCause()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "ParserConfigurationException", + args = {java.lang.String.class} + ) + public void test_ConstructorLjava_lang_String() { + ParserConfigurationException pce = + new ParserConfigurationException("Oops!"); + assertEquals("Oops!", pce.getMessage()); + assertEquals("Oops!", pce.getLocalizedMessage()); + assertNull(pce.getCause()); + } + +} diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java new file mode 100644 index 0000000..5d41356 --- /dev/null +++ b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java @@ -0,0 +1,547 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tests.api.javax.xml.parsers; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Properties; +import java.util.Vector; + +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import junit.framework.TestCase; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.helpers.DefaultHandler; + +import dalvik.annotation.AndroidOnly; +import dalvik.annotation.KnownFailure; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@TestTargetClass(SAXParserFactory.class) +public class SAXParserFactoryTest extends TestCase { + + SAXParserFactory spf; + + InputStream is1; + + static HashMap<String, String> ns; + + static Vector<String> el; + + static HashMap<String, String> attr; + + public void setUp() throws Exception { + spf = SAXParserFactory.newInstance(); + + is1 = getClass().getResourceAsStream("/simple.xml"); + + ns = new HashMap<String, String>(); + attr = new HashMap<String, String>(); + el = new Vector<String>(); + } + + public void tearDown() throws Exception { + is1.close(); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "SAXParserFactory", + args = {} + ) + @AndroidOnly("Android SAX implementation is non-validating") + public void test_Constructor() { + MySAXParserFactory mpf = new MySAXParserFactory(); + assertTrue(mpf instanceof SAXParserFactory); + assertFalse(mpf.isValidating()); + } + + /** + * @tests javax.xml.parsers.SAXParserFactory#getSchema(). + * TBD getSchema() IS NOT SUPPORTED + */ + /* public void test_getSchema() { + assertNull(spf.getSchema()); + SchemaFactory sf = + SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + Schema schema = sf.newSchema(); + spf.setSchema(schema); + assertNotNull(spf.getSchema()); + } catch (SAXException sax) { + fail("Unexpected exception " + sax.toString()); + } + } + */ + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isNamespaceAware", + args = {} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "setNamespaceAware", + args = {boolean.class} + ) + }) + public void test_setIsNamespaceAware() { + spf.setNamespaceAware(true); + assertTrue(spf.isNamespaceAware()); + spf.setNamespaceAware(false); + assertFalse(spf.isNamespaceAware()); + spf.setNamespaceAware(true); + assertTrue(spf.isNamespaceAware()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isValidating", + args = {} + ), + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "", + method = "setValidating", + args = {boolean.class} + ) + }) + public void test_setIsValidating() { + spf.setValidating(true); + assertTrue(spf.isValidating()); + spf.setValidating(false); + assertFalse(spf.isValidating()); + spf.setValidating(true); + assertTrue(spf.isValidating()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isXIncludeAware", + args = {} + ), + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "", + method = "setXIncludeAware", + args = {boolean.class} + ) + }) + @KnownFailure("Should handle XIncludeAware flag more gracefully") + public void test_setIsXIncludeAware() { + spf.setXIncludeAware(true); + assertTrue(spf.isXIncludeAware()); + spf.setXIncludeAware(false); + assertFalse(spf.isXIncludeAware()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "newInstance", + args = {} + ) + public void test_newInstance() { + String className = null; + try { + SAXParserFactory dtf = SAXParserFactory.newInstance(); + assertNotNull("New Instance of DatatypeFactory is null", dtf); + + className = System.getProperty("javax.xml.parsers.SAXParserFactory"); + + System.setProperty("javax.xml.parsers.SAXParserFactory", + "org.apache.harmony.xml.parsers.SAXParserFactoryImpl"); + + SAXParserFactory spf1 = SAXParserFactory.newInstance(); + assertTrue(spf1 instanceof org.apache.harmony.xml.parsers.SAXParserFactoryImpl); + + String key = "javax.xml.parsers.SAXParserFactory = org.apache.harmony.xml.parsers.SAXParserFactoryImpl"; + + ByteArrayInputStream bis = new ByteArrayInputStream(key.getBytes()); + Properties prop = System.getProperties(); + prop.load(bis); + SAXParserFactory spf2 = SAXParserFactory.newInstance(); + assertTrue(spf2 instanceof org.apache.harmony.xml.parsers.SAXParserFactoryImpl); + + System.setProperty("javax.xml.parsers.SAXParserFactory", ""); + try { + SAXParserFactory.newInstance(); + fail("Expected FactoryConfigurationError was not thrown"); + } catch (FactoryConfigurationError e) { + // expected + } + } catch (IOException ioe) { + fail("Unexpected exception " + ioe.toString()); + } finally { + if (className == null) { + System.clearProperty("javax.xml.parsers.SAXParserFactory"); + } else { + System.setProperty("javax.xml.parsers.SAXParserFactory", + className); + } + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "SAXException untested; unused on Android", + method = "newSAXParser", + args = {} + ) + public void test_newSAXParser() { + // Ordinary case + try { + SAXParser sp = spf.newSAXParser(); + assertTrue(sp instanceof SAXParser); + sp.parse(is1, new MyHandler()); + } catch(Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Exception case + spf.setValidating(true); + try { + SAXParser sp = spf.newSAXParser(); + } catch(ParserConfigurationException e) { + // Expected, since Android doesn't have a validating parser. + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.SUFFICIENT, + method = "setFeature", + notes = "ParserConfigurationException untested; unused on Android", + args = {java.lang.String.class, boolean.class} + ), + @TestTargetNew( + level = TestLevel.SUFFICIENT, + method = "getFeature", + notes = "ParserConfigurationException untested; unused on Android", + args = {java.lang.String.class} + ) + }) + public void test_setFeatureLjava_lang_StringZ() { + // We can't verify ParserConfigurationException and + // SAXNotSupportedException since these are never + // thrown by Android. + + String[] features = { + "http://xml.org/sax/features/namespaces", + "http://xml.org/sax/features/validation" }; + for (int i = 0; i < features.length; i++) { + try { + spf.setFeature(features[i], true); + assertTrue(spf.getFeature(features[i])); + spf.setFeature(features[i], false); + assertFalse(spf.getFeature(features[i])); + } catch (ParserConfigurationException pce) { + fail("ParserConfigurationException is thrown"); + } catch (SAXNotRecognizedException snre) { + fail("SAXNotRecognizedException is thrown"); + } catch (SAXNotSupportedException snse) { + fail("SAXNotSupportedException is thrown"); + } + } + + try { + spf.setFeature("", true); + fail("SAXNotRecognizedException is not thrown"); + } catch (ParserConfigurationException pce) { + fail("ParserConfigurationException is thrown"); + } catch (SAXNotRecognizedException snre) { + //expected + } catch (SAXNotSupportedException snse) { + fail("SAXNotSupportedException is thrown"); + } catch (NullPointerException npe) { + fail("NullPointerException is thrown"); + } + + try { + spf.setFeature("http://xml.org/sax/features/unknown-feature", true); + } catch (ParserConfigurationException pce) { + fail("ParserConfigurationException is thrown"); + } catch (SAXNotRecognizedException snre) { + fail("SAXNotRecognizedException is thrown"); + } catch (SAXNotSupportedException snse) { + // Acceptable, although this doesn't happen an Android. + } catch (NullPointerException npe) { + fail("NullPointerException is thrown"); + } + + try { + spf.setFeature(null, true); + fail("NullPointerException is not thrown"); + } catch (ParserConfigurationException pce) { + fail("ParserConfigurationException is thrown"); + } catch (SAXNotRecognizedException snre) { + fail("SAXNotRecognizedException is thrown"); + } catch (SAXNotSupportedException snse) { + fail("SAXNotSupportedException is thrown"); + } catch (NullPointerException npe) { + // expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setNamespaceAware", + args = {boolean.class} + ) + @KnownFailure("Error in namespace feature handling (for ExpatParser)") + public void test_setNamespaceAwareZ() { + + spf.setNamespaceAware(true); + MyHandler mh = new MyHandler(); + InputStream is = getClass().getResourceAsStream("/simple_ns.xml"); + try { + spf.newSAXParser().parse(is, mh); + } catch(javax.xml.parsers.ParserConfigurationException pce) { + fail("ParserConfigurationException was thrown during parsing"); + } catch(org.xml.sax.SAXException se) { + fail("SAXException was thrown during parsing"); + } catch(IOException ioe) { + fail("IOException was thrown during parsing"); + } finally { + try { + is.close(); + } catch(Exception e) {} + } + spf.setNamespaceAware(false); + is = getClass().getResourceAsStream("/simple_ns.xml"); + try { + is = getClass().getResourceAsStream("/simple_ns.xml"); + spf.newSAXParser().parse(is, mh); + } catch(javax.xml.parsers.ParserConfigurationException pce) { + fail("ParserConfigurationException was thrown during parsing"); + } catch(org.xml.sax.SAXException se) { + se.printStackTrace(); + fail("SAXException was thrown during parsing"); + } catch(IOException ioe) { + fail("IOException was thrown during parsing"); + } finally { + try { + is.close(); + } catch(Exception ioee) {} + } + is = getClass().getResourceAsStream("/simple_ns.xml"); + try { + spf.setNamespaceAware(true); + spf.newSAXParser().parse(is, mh); + } catch(javax.xml.parsers.ParserConfigurationException pce) { + fail("ParserConfigurationException was thrown during parsing"); + } catch(org.xml.sax.SAXException se) { + fail("SAXException was thrown during parsing"); + } catch(IOException ioe) { + fail("IOException was thrown during parsing"); + } finally { + try { + is.close(); + } catch(Exception ioee) {} + } + } + + /* public void test_setSchemaLjavax_xml_validation_Schema() { + SchemaFactory sf = + SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + Schema schema = sf.newSchema(); + spf.setSchema(schema); + assertNotNull(spf.getSchema()); + } catch (SAXException sax) { + fail("Unexpected exception " + sax.toString()); + } + } + */ + +// public void test_setValidatingZ() { +// MyHandler mh = new MyHandler(); +// InputStream is2 = getClass().getResourceAsStream("/recipe.xml"); +// try { +// spf.setValidating(true); +// assertTrue(spf.isValidating()); +// spf.newSAXParser().parse(is2, mh); +// } catch (org.xml.sax.SAXException se) { +// fail("SAXException was thrown during parsing"); +// } catch (javax.xml.parsers.ParserConfigurationException pce) { +// fail("ParserConfigurationException was thrown during parsing"); +// } catch (IOException ioe) { +// fail("IOException was thrown during parsing"); +// } finally { +// try { +// is2.close(); +// } catch(Exception ioee) {} +// } +// InputStream is3 = getClass().getResourceAsStream("/recipe1.xml"); +// try { +// assertTrue(spf.isValidating()); +// spf.newSAXParser().parse(is3, mh); +// } catch (org.xml.sax.SAXException se) { +// fail("SAXException was thrown during parsing"); +// } catch (javax.xml.parsers.ParserConfigurationException pce) { +// fail("ParserConfigurationException was thrown during parsing"); +// } catch (IOException ioe) { +// fail("IOEXception was thrown during parsing: " + ioe.getMessage()); +// } finally { +// try { +// is3.close(); +// } catch(Exception ioee) {} +// } +// is2 = getClass().getResourceAsStream("/recipe.xml"); +// try { +// spf.setValidating(false); +// assertFalse(spf.isValidating()); +// spf.newSAXParser().parse(is2, mh); +// } catch (org.xml.sax.SAXException se) { +// fail("SAXException was thrown during parsing"); +// } catch (javax.xml.parsers.ParserConfigurationException pce) { +// fail("ParserConfigurationException was thrown during parsing"); +// } catch (IOException ioe) { +// fail("IOException was thrown during parsing"); +// } finally { +// try { +// is2.close(); +// } catch(Exception ioee) {} +// } +// is3 = getClass().getResourceAsStream("/recipe1.xml"); +// try { +// assertFalse(spf.isValidating()); +// spf.newSAXParser().parse(is3, mh); +// } catch (org.xml.sax.SAXException se) { +// fail("SAXException was thrown during parsing"); +// } catch (javax.xml.parsers.ParserConfigurationException pce) { +// fail("ParserConfigurationException was thrown during parsing"); +// } catch (IOException ioe) { +// fail("IOEXception was thrown during parsing: " + ioe.getMessage()); +// } finally { +// try { +// is3.close(); +// } catch(Exception ioee) {} +// } +// } + +// public void test_setXIncludeAwareZ() { +// spf.setXIncludeAware(true); +// MyHandler mh = new MyHandler(); +// InputStream is = getClass().getResourceAsStream("/simple_ns.xml"); +// try { +// spf.newSAXParser().parse(is, mh); +// } catch(javax.xml.parsers.ParserConfigurationException pce) { +// fail("ParserConfigurationException was thrown during parsing"); +// } catch(org.xml.sax.SAXException se) { +// fail("SAXException was thrown during parsing"); +// } catch(IOException ioe) { +// fail("IOException was thrown during parsing"); +// } finally { +// try { +// is.close(); +// } catch(Exception ioee) {} +// } +// spf.setXIncludeAware(false); +// is = getClass().getResourceAsStream("/simple_ns.xml"); +// try { +// is = getClass().getResourceAsStream("/simple_ns.xml"); +// spf.newSAXParser().parse(is, mh); +// } catch(javax.xml.parsers.ParserConfigurationException pce) { +// fail("ParserConfigurationException was thrown during parsing"); +// } catch(org.xml.sax.SAXException se) { +// fail("SAXException was thrown during parsing"); +// } catch(IOException ioe) { +// fail("IOException was thrown during parsing"); +// } finally { +// try { +// is.close(); +// } catch(Exception ioee) {} +// } +// is = getClass().getResourceAsStream("/simple_ns.xml"); +// try { +// spf.setXIncludeAware(true); +// spf.newSAXParser().parse(is, mh); +// } catch(javax.xml.parsers.ParserConfigurationException pce) { +// fail("ParserConfigurationException was thrown during parsing"); +// } catch(org.xml.sax.SAXException se) { +// fail("SAXException was thrown during parsing"); +// } catch(IOException ioe) { +// fail("IOException was thrown during parsing"); +// } finally { +// try { +// is.close(); +// } catch(Exception ioee) {} +// } +// } + + static class MyHandler extends DefaultHandler { + + public void startElement(String uri, String localName, String qName, + Attributes atts) { + + el.add(qName); + if (!uri.equals("")) + ns.put(qName, uri); + for (int i = 0; i < atts.getLength(); i++) { + attr.put(atts.getQName(i), atts.getValue(i)); + } + + } + } + + class MySAXParserFactory extends SAXParserFactory { + + public MySAXParserFactory() { + super(); + } + + public SAXParser newSAXParser() { + return null; + } + + public void setFeature(String name, boolean value) throws + ParserConfigurationException, SAXNotRecognizedException, + SAXNotSupportedException { + + } + + public boolean getFeature(String name) throws + ParserConfigurationException, SAXNotRecognizedException, + SAXNotSupportedException { + return true; + } + + } + +} diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java new file mode 100644 index 0000000..4ca0f1f --- /dev/null +++ b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java @@ -0,0 +1,1171 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tests.api.javax.xml.parsers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Vector; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import junit.framework.TestCase; + +import org.xml.sax.HandlerBase; +import org.xml.sax.InputSource; +import org.xml.sax.Parser; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.helpers.DefaultHandler; + +import tests.api.javax.xml.parsers.SAXParserTestSupport.MyDefaultHandler; +import tests.api.javax.xml.parsers.SAXParserTestSupport.MyHandler; +import tests.api.org.xml.sax.support.BrokenInputStream; +import tests.api.org.xml.sax.support.MethodLogger; +import tests.api.org.xml.sax.support.MockHandler; +import dalvik.annotation.KnownFailure; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@SuppressWarnings("deprecation") +@TestTargetClass(SAXParser.class) +public class SAXParserTest extends TestCase { + + private class MockSAXParser extends SAXParser { + public MockSAXParser() { + super(); + } + + /* + * @see javax.xml.parsers.SAXParser#getParser() + */ + @Override + public Parser getParser() throws SAXException { + // it is a fake + return null; + } + + /* + * @see javax.xml.parsers.SAXParser#getProperty(java.lang.String) + */ + @Override + public Object getProperty(String name) throws SAXNotRecognizedException, + SAXNotSupportedException { + // it is a fake + return null; + } + + /* + * @see javax.xml.parsers.SAXParser#getXMLReader() + */ + @Override + public XMLReader getXMLReader() throws SAXException { + // it is a fake + return null; + } + + /* + * @see javax.xml.parsers.SAXParser#isNamespaceAware() + */ + @Override + public boolean isNamespaceAware() { + // it is a fake + return false; + } + + /* + * @see javax.xml.parsers.SAXParser#isValidating() + */ + @Override + public boolean isValidating() { + // it is a fake + return false; + } + + /* + * @see javax.xml.parsers.SAXParser#setProperty(java.lang.String, + * java.lang.Object) + */ + @Override + public void setProperty(String name, Object value) throws + SAXNotRecognizedException, SAXNotSupportedException { + // it is a fake + } + } + + private static final String LEXICAL_HANDLER_PROPERTY + = "http://xml.org/sax/properties/lexical-handler"; + + SAXParserFactory spf; + + SAXParser parser; + + static HashMap<String, String> ns; + + static Vector<String> el; + + static HashMap<String, String> attr; + + SAXParserTestSupport sp = new SAXParserTestSupport(); + + File [] list_wf; + File [] list_nwf; + File [] list_out_dh; + File [] list_out_hb; + + boolean validating = false; + + private InputStream getResource(String name) { + return this.getClass().getResourceAsStream(name); + } + + public SAXParserTest() throws Exception{ + // we differntiate between a validating and a non validating parser + try { + SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); + validating = parser.isValidating(); + } catch (Exception e) { + fail("could not obtain a SAXParser"); + } + + // nwf = non well formed, wf = well formed + list_wf = new File[] {File.createTempFile( + SAXParserTestSupport.XML_WF + "staff","xml")}; + list_nwf = new File[] {File.createTempFile( + SAXParserTestSupport.XML_NWF + "staff","xml")}; + + copyFile(getResource(SAXParserTestSupport.XML_WF + "staff.xml"), + list_wf[0].getAbsolutePath()); + copyFile(getResource(SAXParserTestSupport.XML_WF + "staff.dtd"), + File.createTempFile(SAXParserTestSupport.XML_WF + "staff", + "dtd").getAbsolutePath()); + copyFile(getResource(SAXParserTestSupport.XML_NWF + "staff.xml"), + list_nwf[0].getAbsolutePath()); + copyFile(getResource(SAXParserTestSupport.XML_NWF + "staff.dtd"), + File.createTempFile(SAXParserTestSupport.XML_NWF + "staff", + "dtd").getAbsolutePath()); + + list_out_dh = new File[] {File.createTempFile( + SAXParserTestSupport.XML_WF_OUT_DH + "staff", "out")}; + list_out_hb = new File[] {File.createTempFile( + SAXParserTestSupport.XML_WF_OUT_HB + "staff", "out")}; + copyFile(getResource(SAXParserTestSupport.XML_WF_OUT_HB + "staff.out"), + list_out_hb[0].getAbsolutePath()); + copyFile(getResource(SAXParserTestSupport.XML_WF_OUT_DH + "staff.out"), + list_out_dh[0].getAbsolutePath()); + } + + private void copyFile(InputStream toCopy, String target) throws Exception { + new File(target).getParentFile().mkdirs(); + OutputStream writer = new FileOutputStream(target); + byte[] buffer = new byte[512]; + int i = toCopy.read(buffer); + while (i >= 0) { + writer.write(buffer,0,i); + i = toCopy.read(buffer); + } + writer.flush(); + writer.close(); + toCopy.close(); + } + + @Override + protected void setUp() throws Exception { + spf = SAXParserFactory.newInstance(); + parser = spf.newSAXParser(); + assertNotNull(parser); + + ns = new HashMap<String, String>(); + attr = new HashMap<String, String>(); + el = new Vector<String>(); + } + + @Override + protected void tearDown() throws Exception { + } + +// public static void main(String[] args) throws Exception { +// SAXParserTest st = new SAXParserTest(); +// st.setUp(); +// st.generateDataFromReferenceImpl(); +// +// } +// +// private void generateDataFromReferenceImpl() { +// try { +// for(int i = 0; i < list_wf.length; i++) { +// MyDefaultHandler dh = new MyDefaultHandler(); +// InputStream is = new FileInputStream(list_wf[i]); +// parser.parse(is, dh, ParsingSupport.XML_SYSTEM_ID); +// HashMap refHm = dh.createData(); +// +// StringBuilder sb = new StringBuilder(); +// for (int j = 0; j < ParsingSupport.KEYS.length; j++) { +// String key = ParsingSupport.KEYS[j]; +// sb.append(refHm.get(key)).append( +// ParsingSupport.SEPARATOR_DATA); +// } +// FileWriter fw = new FileWriter("/tmp/build_dh"+i+".out"); +// fw.append(sb.toString()); +// fw.close(); +// } +// +// for(int i = 0; i < list_nwf.length; i++) { +// MyHandler hb = new MyHandler(); +// InputStream is = new FileInputStream(list_wf[i]); +// parser.parse(is, hb, ParsingSupport.XML_SYSTEM_ID); +// HashMap refHm = hb.createData(); +// +// StringBuilder sb = new StringBuilder(); +// for (int j = 0; j < ParsingSupport.KEYS.length; j++) { +// String key = ParsingSupport.KEYS[j]; +// sb.append(refHm.get(key)).append( +// ParsingSupport.SEPARATOR_DATA); +// } +// FileWriter fw = new FileWriter("/tmp/build_hb"+i+".out"); +// fw.append(sb.toString()); +// fw.close(); +// } +// +// +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "SAXParser", + args = {} + ) + public void testSAXParser() { + try { + new MockSAXParser(); + } catch (Exception e) { + fail("unexpected exception " + e.toString()); + } + } + + /** + * @tests javax.xml.parser.SAXParser#getSchema(). + * TODO getSchema() IS NOT SUPPORTED + */ + /* public void test_getSchema() { + assertNull(parser.getSchema()); + SchemaFactory sf = + SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + Schema schema = sf.newSchema(); + spf.setSchema(schema); + assertNotNull(spf.newSAXParser().getSchema()); + } catch (ParserConfigurationException pce) { + fail("Unexpected ParserConfigurationException " + pce.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + */ + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "isNamespaceAware", + args = {} + ) + public void testIsNamespaceAware() { + try { + spf.setNamespaceAware(true); + assertTrue(spf.newSAXParser().isNamespaceAware()); + spf.setNamespaceAware(false); + assertFalse(spf.newSAXParser().isNamespaceAware()); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "No validating parser in Android, hence not tested", + method = "isValidating", + args = {} + ) + public void testIsValidating() { + try { + spf.setValidating(false); + assertFalse(spf.newSAXParser().isValidating()); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "No XInclude-aware parser in Android, hence not tested", + method = "isXIncludeAware", + args = {} + ) + @KnownFailure("Should handle XIncludeAware flag more gracefully") + public void testIsXIncludeAware() { + try { + spf.setXIncludeAware(false); + assertFalse(spf.newSAXParser().isXIncludeAware()); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + /** + * @test javax.xml.parsers.SAXParser#parse(java.io.File, + * org.xml.sax.helpers.DefaultHandler) + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify positive functionality properly; not all exceptions are verified.", + method = "parse", + args = {java.io.File.class, org.xml.sax.helpers.DefaultHandler.class} + ) + public void _test_parseLjava_io_FileLorg_xml_sax_helpers_DefaultHandler() + throws Exception { + + for(int i = 0; i < list_wf.length; i++) { + HashMap<String, String> hm = + new SAXParserTestSupport().readFile(list_out_dh[i].getPath()); + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse(list_wf[i], dh); + assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData())); + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse(list_nwf[i], dh); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } + } + + try { + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse((File) null, dh); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } + + try { + parser.parse(list_wf[0], (DefaultHandler) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "Sufficient while XML parser situation is still unclear", + method = "parse", + args = {java.io.File.class, org.xml.sax.HandlerBase.class} + ) + public void testParseFileHandlerBase() { + for(int i = 0; i < list_wf.length; i++) { + try { + HashMap<String, String> hm = sp.readFile( + list_out_hb[i].getPath()); + MyHandler dh = new MyHandler(); + parser.parse(list_wf[i], dh); + assertTrue(SAXParserTestSupport.equalsMaps(hm, + dh.createData())); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyHandler dh = new MyHandler(); + parser.parse(list_nwf[i], dh); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } + } + + try { + MyHandler dh = new MyHandler(); + parser.parse((File) null, dh); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + try { + parser.parse(list_wf[0], (HandlerBase) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch(IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + + /** + * @test javax.xml.parsers.SAXParser#parse(org.xml.sax.InputSource, + * org.xml.sax.helpers.DefaultHandler) + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify IOException.", + method = "parse", + args = {org.xml.sax.InputSource.class, org.xml.sax.helpers.DefaultHandler.class} + ) + + public void _test_parseLorg_xml_sax_InputSourceLorg_xml_sax_helpers_DefaultHandler() + throws Exception { + + for(int i = 0; i < list_wf.length; i++) { + + HashMap<String, String> hm = new SAXParserTestSupport().readFile( + list_out_dh[i].getPath()); + MyDefaultHandler dh = new MyDefaultHandler(); + InputSource is = new InputSource(new FileInputStream(list_wf[i])); + parser.parse(is, dh); + assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData())); + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyDefaultHandler dh = new MyDefaultHandler(); + InputSource is = new InputSource( + new FileInputStream(list_nwf[i])); + parser.parse(is, dh); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } + } + + try { + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse((InputSource) null, dh); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } + + try { + InputSource is = new InputSource(new FileInputStream(list_wf[0])); + parser.parse(is, (DefaultHandler) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } + + try { + InputSource is = new InputSource(new BrokenInputStream(new FileInputStream(list_wf[0]), 10)); + parser.parse(is, (DefaultHandler) null); + fail("IOException expected"); + } catch(IOException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "Sufficient while XML parser situation is still unclear", + method = "parse", + args = {org.xml.sax.InputSource.class, org.xml.sax.HandlerBase.class} + ) + public void testParseInputSourceHandlerBase() { + for(int i = 0; i < list_wf.length; i++) { + try { + HashMap<String, String> hm = sp.readFile( + list_out_hb[i].getPath()); + MyHandler dh = new MyHandler(); + InputSource is = new InputSource(new FileInputStream(list_wf[i])); + parser.parse(is, dh); + assertTrue(SAXParserTestSupport.equalsMaps(hm, + dh.createData())); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyHandler dh = new MyHandler(); + InputSource is = new InputSource(new FileInputStream(list_nwf[i])); + parser.parse(is, dh); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } + } + + try { + MyHandler dh = new MyHandler(); + parser.parse((InputSource) null, dh); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + try { + InputSource is = new InputSource(new FileInputStream(list_wf[0])); + parser.parse(is, (HandlerBase) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch(IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // Reader case + try { + InputSource is = new InputSource(new InputStreamReader( + new FileInputStream(list_wf[0]))); + parser.parse(is, (HandlerBase) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch(IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // SystemID case + try { + InputSource is = new InputSource(list_wf[0].toURI().toString()); + parser.parse(is, (HandlerBase) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch(IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // Inject IOException + try { + InputStream is = new BrokenInputStream( + new FileInputStream(list_wf[0]), 10); + parser.parse(is, (HandlerBase) null, + SAXParserTestSupport.XML_SYSTEM_ID); + fail("IOException expected"); + } catch(IOException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + /** + * @test javax.xml.parsers.SAXParser#parse(java.io.InputStream, + * org.xml.sax.helpers.DefaultHandler) + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify IOException.", + method = "parse", + args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class} + ) + public void _test_parseLjava_io_InputStreamLorg_xml_sax_helpers_DefaultHandler() + throws Exception { + + for(int i = 0; i < list_wf.length; i++) { + + HashMap<String, String> hm = new SAXParserTestSupport().readFile( + list_out_dh[i].getPath()); + MyDefaultHandler dh = new MyDefaultHandler(); + InputStream is = new FileInputStream(list_wf[i]); + parser.parse(is, dh); + assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData())); + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyDefaultHandler dh = new MyDefaultHandler(); + InputStream is = new FileInputStream(list_nwf[i]); + parser.parse(is, dh); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } + } + + try { + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse((InputStream) null, dh); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } + + try { + InputStream is = new FileInputStream(list_wf[0]); + parser.parse(is, (DefaultHandler) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } + } + + /** + * @test javax.xml.parsers.SAXParser#parse(java.io.InputStream, + * org.xml.sax.helpers.DefaultHandler, java.lang.String) + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify IOException.", + method = "parse", + args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class, java.lang.String.class} + ) + public void _test_parseLjava_io_InputStreamLorg_xml_sax_helpers_DefaultHandlerLjava_lang_String() { + for(int i = 0; i < list_wf.length; i++) { + try { + HashMap<String, String> hm = sp.readFile( + list_out_hb[i].getPath()); + MyDefaultHandler dh = new MyDefaultHandler(); + InputStream is = new FileInputStream(list_wf[i]); + parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID); + assertTrue(SAXParserTestSupport.equalsMaps(hm, + dh.createData())); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyDefaultHandler dh = new MyDefaultHandler(); + InputStream is = new FileInputStream(list_nwf[i]); + parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } + } + + try { + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse((InputStream) null, dh, + SAXParserTestSupport.XML_SYSTEM_ID); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + try { + InputStream is = new FileInputStream(list_wf[0]); + parser.parse(is, (DefaultHandler) null, + SAXParserTestSupport.XML_SYSTEM_ID); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch(IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } +// +// for(int i = 0; i < list_wf.length; i++) { +// +// HashMap<String, String> hm = new SAXParserTestSupport().readFile( +// list_out_dh[i].getPath()); +// MyDefaultHandler dh = new MyDefaultHandler(); +// InputStream is = new FileInputStream(list_wf[i]); +// parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID); +// assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData())); +// } +// +// for(int i = 0; i < list_nwf.length; i++) { +// try { +// MyDefaultHandler dh = new MyDefaultHandler(); +// InputStream is = new FileInputStream(list_nwf[i]); +// parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID); +// fail("SAXException is not thrown"); +// } catch(org.xml.sax.SAXException se) { +// //expected +// } +// } +// +// try { +// MyDefaultHandler dh = new MyDefaultHandler(); +// parser.parse((InputStream) null, dh, +// SAXParserTestSupport.XML_SYSTEM_ID); +// fail("java.lang.IllegalArgumentException is not thrown"); +// } catch(java.lang.IllegalArgumentException iae) { +// //expected +// } +// +// try { +// InputStream is = new FileInputStream(list_wf[0]); +// parser.parse(is, (DefaultHandler) null, +// SAXParserTestSupport.XML_SYSTEM_ID); +// } catch(java.lang.IllegalArgumentException iae) { +// fail("java.lang.IllegalArgumentException is thrown"); +// } +// +// // TODO commented out since our parser is nonvalidating and thus never +// // tries to load staff.dtd in "/" ... and therefore never can fail with +// // an IOException +// /*try { +// MyDefaultHandler dh = new MyDefaultHandler(); +// InputStream is = new FileInputStream(list_wf[0]); +// parser.parse(is, dh, "/"); +// fail("Expected IOException was not thrown"); +// } catch(IOException ioe) { +// // expected +// }*/ + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "Sufficient while XML parser situation is still unclear", + method = "parse", + args = {java.io.InputStream.class, org.xml.sax.HandlerBase.class} + ) + public void testParseInputStreamHandlerBase() { + for(int i = 0; i < list_wf.length; i++) { + try { + HashMap<String, String> hm = sp.readFile( + list_out_hb[i].getPath()); + MyHandler dh = new MyHandler(); + InputStream is = new FileInputStream(list_wf[i]); + parser.parse(is, dh); + assertTrue(SAXParserTestSupport.equalsMaps(hm, + dh.createData())); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyHandler dh = new MyHandler(); + InputStream is = new FileInputStream(list_nwf[i]); + parser.parse(is, dh); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } + } + + try { + MyHandler dh = new MyHandler(); + parser.parse((InputStream) null, dh); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + try { + InputStream is = new FileInputStream(list_wf[0]); + parser.parse(is, (HandlerBase) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch(IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // Inject IOException + try { + InputStream is = new BrokenInputStream( + new FileInputStream(list_wf[0]), 10); + parser.parse(is, (HandlerBase) null); + fail("IOException expected"); + } catch(IOException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "Sufficient while XML parser situation is still unclear", + method = "parse", + args = {java.io.InputStream.class, org.xml.sax.HandlerBase.class, java.lang.String.class} + ) + public void testParseInputStreamHandlerBaseString() { + for(int i = 0; i < list_wf.length; i++) { + try { + HashMap<String, String> hm = sp.readFile( + list_out_hb[i].getPath()); + MyHandler dh = new MyHandler(); + InputStream is = new FileInputStream(list_wf[i]); + parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID); + assertTrue(SAXParserTestSupport.equalsMaps(hm, + dh.createData())); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyHandler dh = new MyHandler(); + InputStream is = new FileInputStream(list_nwf[i]); + parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } + } + + try { + MyHandler dh = new MyHandler(); + parser.parse((InputStream) null, dh, + SAXParserTestSupport.XML_SYSTEM_ID); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + try { + InputStream is = new FileInputStream(list_wf[0]); + parser.parse(is, (HandlerBase) null, + SAXParserTestSupport.XML_SYSTEM_ID); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch(IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + // Inject IOException + try { + InputStream is = new BrokenInputStream( + new FileInputStream(list_wf[0]), 10); + parser.parse(is, (HandlerBase) null, + SAXParserTestSupport.XML_SYSTEM_ID); + fail("IOException expected"); + } catch(IOException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + /** + * @test javax.xml.parsers.SAXParser#parse(java.lang.String, + * org.xml.sax.helpers.DefaultHandler) + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify IOException.", + method = "parse", + args = {java.lang.String.class, org.xml.sax.helpers.DefaultHandler.class} + ) + public void _test_parseLjava_lang_StringLorg_xml_sax_helpers_DefaultHandler() + throws Exception { + + for(int i = 0; i < list_wf.length; i++) { + + HashMap<String, String> hm = new SAXParserTestSupport().readFile( + list_out_dh[i].getPath()); + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse(list_wf[i].getPath(), dh); + assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData())); + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse(list_nwf[i].getPath(), dh); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } + } + + try { + MyDefaultHandler dh = new MyDefaultHandler(); + parser.parse((String) null, dh); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } + + try { + parser.parse(list_wf[0].getPath(), (DefaultHandler) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "Sufficient while XML parser situation is still unclear", + method = "parse", + args = {java.lang.String.class, org.xml.sax.HandlerBase.class} + ) + public void testParseStringHandlerBase() { + for(int i = 0; i < list_wf.length; i++) { + try { + HashMap<String, String> hm = sp.readFile( + list_out_hb[i].getPath()); + MyHandler dh = new MyHandler(); + parser.parse(list_wf[i].toURI().toString(), dh); + assertTrue(SAXParserTestSupport.equalsMaps(hm, + dh.createData())); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch (SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + + for(int i = 0; i < list_nwf.length; i++) { + try { + MyHandler dh = new MyHandler(); + parser.parse(list_nwf[i].toURI().toString(), dh); + fail("SAXException is not thrown"); + } catch(org.xml.sax.SAXException se) { + //expected + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } + } + + try { + MyHandler dh = new MyHandler(); + parser.parse((String) null, dh); + fail("java.lang.IllegalArgumentException is not thrown"); + } catch(java.lang.IllegalArgumentException iae) { + //expected + } catch (IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + + try { + parser.parse(list_wf[0].toURI().toString(), (HandlerBase) null); + } catch(java.lang.IllegalArgumentException iae) { + fail("java.lang.IllegalArgumentException is thrown"); + } catch (FileNotFoundException fne) { + fail("Unexpected FileNotFoundException " + fne.toString()); + } catch(IOException ioe) { + fail("Unexpected IOException " + ioe.toString()); + } catch(SAXException sax) { + fail("Unexpected SAXException " + sax.toString()); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "reset", + args = { } + ) + @KnownFailure("Android DocumentBuilder should implement reset() properly") + public void testReset() { + try { + spf = SAXParserFactory.newInstance(); + parser = spf.newSAXParser(); + + parser.setProperty(LEXICAL_HANDLER_PROPERTY, new MockHandler(new MethodLogger())); + parser.reset(); + assertEquals(null, parser.getProperty(LEXICAL_HANDLER_PROPERTY)); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getParser", + args = { } + ) + public void testGetParser() { + spf = SAXParserFactory.newInstance(); + try { + Parser parser = spf.newSAXParser().getParser(); + assertNotNull(parser); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getXMLReader", + args = { } + ) + public void testGetReader() { + spf = SAXParserFactory.newInstance(); + try { + XMLReader reader = spf.newSAXParser().getXMLReader(); + assertNotNull(reader); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getProperty", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setProperty", + args = { String.class, Object.class } + ) + }) + @KnownFailure("ExpatParser should allow to clear properties") + public void testSetGetProperty() { + // Ordinary case + String validName = "http://xml.org/sax/properties/lexical-handler"; + LexicalHandler validValue = new MockHandler(new MethodLogger()); + + try { + SAXParser parser = spf.newSAXParser(); + parser.setProperty(validName, validValue); + assertEquals(validValue, parser.getProperty(validName)); + + parser.setProperty(validName, null); + assertEquals(null, parser.getProperty(validName)); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Unsupported property + try { + SAXParser parser = spf.newSAXParser(); + parser.setProperty("foo", "bar"); + fail("SAXNotRecognizedException expected"); + } catch (SAXNotRecognizedException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + try { + SAXParser parser = spf.newSAXParser(); + parser.getProperty("foo"); + fail("SAXNotRecognizedException expected"); + } catch (SAXNotRecognizedException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // No name case + try { + SAXParser parser = spf.newSAXParser(); + parser.setProperty(null, "bar"); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + try { + SAXParser parser = spf.newSAXParser(); + parser.getProperty(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + +} + diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java new file mode 100644 index 0000000..bc5e6a1 --- /dev/null +++ b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.javax.xml.parsers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; + +import org.xml.sax.Attributes; +import org.xml.sax.HandlerBase; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Support for SAXParserTest. Shares the element keys used in the golden files. + * Compares the result of the parser with golden data. + * Contains the handler classes used to track the output of the parser. + */ +class SAXParserTestSupport { + + public static final char SEPARATOR_ELEMENT = '^'; + public static final char SEPARATOR_STRING = '$'; + public static final char SEPARATOR_DATA = '#'; + + public static final String XML_WF = "/wf/"; + public static final String XML_NWF = "/nwf/"; + + public static final String XML_WF_OUT_DH = "/out_dh/"; + public static final String XML_WF_OUT_HB = "/out_hb/"; + + public static final String XML_SYSTEM_ID = "." + "/systemid/"; + + public static final String KEY_IS_START_DOC = "isEndDocument"; + public static final String KEY_IS_END_DOC = "isStartDocument"; + public static final String KEY_TEXT = "text"; + public static final String KEY_ERROR = "error"; + public static final String KEY_FATAL_ERROR = "fatalError"; + public static final String KEY_WARNING = "warning"; + public static final String KEY_END_ELEMENT = "endEement"; + public static final String KEY_END_PREFIX_MAPPING = "endPrefixMapping"; + public static final String KEY_IGNORABLE_WHITE_SPACE = + "ignorableWhitespace"; + public static final String KEY_NOTATION_DECL = "notationDecl"; + public static final String KEY_PROCESSING_INSTRUCTION = + "processingInstruction"; + public static final String KEY_RESOLVE_ENTITY = "resolveEntity"; + public static final String KEY_DOCUMENT_LOCATORS = "documentLocators"; + public static final String KEY_SKIPPED_ENTITY = "skippedEntity"; + public static final String KEY_START_ELEMENT = "startElement"; + public static final String KEY_START_PREFIX_MAPPING = "startPrefixMapping"; + public static final String KEY_UNPARSED_ENTITY_DECL = "unparsedEntityDecl"; + + static String [] KEYS = {KEY_IS_START_DOC, KEY_IS_END_DOC, KEY_TEXT, + KEY_ERROR, KEY_FATAL_ERROR, KEY_WARNING, KEY_END_ELEMENT, + KEY_END_PREFIX_MAPPING, KEY_PROCESSING_INSTRUCTION, + KEY_SKIPPED_ENTITY, KEY_START_ELEMENT, + KEY_START_PREFIX_MAPPING}; + + static { + String tmp = System.getProperty("java.io.tmpdir", "."); + + new File(tmp).mkdirs(); + new File(tmp, XML_WF).mkdirs(); + new File(tmp, XML_NWF).mkdirs(); + new File(tmp, XML_WF_OUT_DH).mkdirs(); + new File(tmp, XML_WF_OUT_HB).mkdirs(); + } + + /** + * Initialize the SAXParserTest reference by filling in the data from the + * file passed to the method. This will be the reference to compare + * against with the output of the parser. + */ + public HashMap<String, String> readFile(String fileName) { + HashMap<String, String> storage = new HashMap<String, String>(); + try { + + InputStream is = new FileInputStream(fileName); + + int c = is.read(); + + StringBuffer str = new StringBuffer(); + int i = 0; + while(c != -1) { + if((char)c == SEPARATOR_DATA) { + // if(str.length() > 0) { + if(i < KEYS.length) { + storage.put(KEYS[i], str.toString()); + // System.out.println(str.toString()); + str.setLength(0); + i++; + } + // } + } else { + str.append((char)c); + } + try { + c = is.read(); + } catch (Exception e) { + c = -1; + } + } + try { + is.close(); + } catch (IOException e) { + } + + } catch(IOException ioe) { + System.out.println("IOException during processing the file: " + + fileName); + } + return storage; + } + + /** + * Compares the content of two HashMaps. One map should be the reference + * containing the correct string for each xml document element and the other + * should contain the elements filled with output from the parser. + * + * @param original the reference + * @param result the result of the parser + * @return true if they're equal. + */ + public static boolean equalsMaps(HashMap<String, String> original, + HashMap<String, String> result) { + + if(original == null && result == null) { + return true; + } else { + if(original.size() != result.size()) return false; + + for(int i = 0; i < KEYS.length; i++) { + if(!original.get(KEYS[i]).equals(result.get(KEYS[i]))) { + System.out.println("for "+KEYS[i]+": original:" + + original.get(KEYS[i])); + System.out.println(); + System.out.println(" result:" + result.get(KEYS[i])); + System.out.println(); + return false; + } + } + return true; + } + } + + static class MyDefaultHandler extends DefaultHandler { + + public StringBuffer data_isEndDocument = new StringBuffer(); + public StringBuffer data_isStartDocument = new StringBuffer(); + public StringBuffer data_text = new StringBuffer(); + public StringBuffer data_error = new StringBuffer(); + public StringBuffer data_fatalError = new StringBuffer(); + public StringBuffer data_warning = new StringBuffer(); + public StringBuffer data_endElement = new StringBuffer(); + public StringBuffer data_endPrefixMapping = new StringBuffer(); + public StringBuffer data_processingInstruction = new StringBuffer(); + public StringBuffer data_skippedEntity = new StringBuffer(); + public StringBuffer data_startElement = new StringBuffer(); + public StringBuffer data_startPrefixMapping = new StringBuffer(); + + public HashMap<String, String> createData() { + HashMap<String, String> hm = new HashMap<String, String>(); + hm.put(KEY_IS_END_DOC, data_isEndDocument.toString()); + hm.put(KEY_IS_START_DOC, data_isStartDocument.toString()); + hm.put(KEY_TEXT, data_text.toString()); + hm.put(KEY_ERROR, data_error.toString()); + hm.put(KEY_FATAL_ERROR, data_fatalError.toString()); + hm.put(KEY_WARNING, data_warning.toString()); + hm.put(KEY_END_ELEMENT, data_endElement.toString()); + hm.put(KEY_END_PREFIX_MAPPING, data_endPrefixMapping.toString()); + + hm.put(KEY_PROCESSING_INSTRUCTION, + data_processingInstruction.toString()); + hm.put(KEY_SKIPPED_ENTITY, data_skippedEntity.toString()); + hm.put(KEY_START_ELEMENT, data_startElement.toString()); + hm.put(KEY_START_PREFIX_MAPPING, + data_startPrefixMapping.toString()); + return hm; + } + + public void printMap() { + System.out.print(data_isStartDocument.toString() + SEPARATOR_DATA + + data_isEndDocument.toString() + SEPARATOR_DATA + + data_text.toString() + SEPARATOR_DATA + + data_error.toString()+ SEPARATOR_DATA + + data_fatalError.toString()+ SEPARATOR_DATA + + data_warning.toString()+ SEPARATOR_DATA + + data_endElement.toString() + SEPARATOR_DATA+ + data_endPrefixMapping.toString()+ SEPARATOR_DATA + + data_processingInstruction.toString() + SEPARATOR_DATA + + data_skippedEntity.toString() + SEPARATOR_DATA + + data_startElement.toString() + SEPARATOR_DATA + + data_startPrefixMapping.toString()+ SEPARATOR_DATA); + } + + @Override + public void characters(char[] ch, int start, int length) { + String str = new String(ch, start, length); + data_text.append(str); + // different sax parsers are allowed to handle chunking differently, + // therefore we cannot rely on identical chunks being delivered. + //data_text.append(ParsingSupport.SEPARATOR_ELEMENT); + } + + @Override + public void endDocument() { + data_isEndDocument.append(true); + data_isEndDocument.append(SEPARATOR_ELEMENT); + } + + @Override + public void endElement(String uri, String localName, String qName) { + StringBuffer sb = new StringBuffer(); + sb.append(uri); + sb.append(SEPARATOR_STRING); + sb.append(localName); + sb.append(SEPARATOR_STRING); + sb.append(qName); + data_endElement.append(sb); + data_endElement.append(SEPARATOR_ELEMENT); + } + + @Override + public void endPrefixMapping(String prefix) { + data_endPrefixMapping.append(prefix); + data_endPrefixMapping.append(SEPARATOR_ELEMENT); + } + + @Override + public void error(SAXParseException e) { + data_error.append(e); + data_error.append(SEPARATOR_ELEMENT); + } + + @Override + public void fatalError(SAXParseException e) { + data_fatalError.append(e); + data_fatalError.append(SEPARATOR_ELEMENT); + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) { + /* String s = new String(ch, start, length); + ignorableWhitespace.append(s); + ignorableWhitespace.append(ParsingSupport.SEPARATOR_ELEMENT);*/ + } + + @Override + public void notationDecl(String name, String publicId, + String systemId) { + /* data_notationDecl.append(name + ParsingSupport.SEPARATOR_STRING + + publicId + ParsingSupport.SEPARATOR_STRING + + systemId + ParsingSupport.SEPARATOR_STRING); + data_notationDecl.append(ParsingSupport.SEPARATOR_ELEMENT);*/ + } + + @Override + public void processingInstruction(String target, String data) { + data_processingInstruction.append(target + SEPARATOR_STRING + data); + data_processingInstruction.append(SEPARATOR_ELEMENT); + } + + @Override + public InputSource resolveEntity(String publicId, String systemId) { + // data_resolveEntity.append(publicId + + // ParsingSupport.SEPARATOR_STRING + systemId); + // data_resolveEntity.append(ParsingSupport.SEPARATOR_ELEMENT); + return null; + } + + @Override + public void setDocumentLocator(Locator locator) { + // data_documentLocators.append(locator); + // data_documentLocators.append(ParsingSupport.SEPARATOR_ELEMENT); + } + + @Override + public void skippedEntity(String name) { + data_skippedEntity.append(name); + data_skippedEntity.append(SEPARATOR_ELEMENT); + } + + @Override + public void startDocument() { + data_isStartDocument.append(true); + data_isStartDocument.append(SEPARATOR_ELEMENT); + } + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) { + data_startElement.append(uri); + data_startElement.append(SEPARATOR_STRING); + data_startElement.append(localName); + data_startElement.append(SEPARATOR_STRING); + data_startElement.append(qName); + + for(int i = 0; i < attributes.getLength(); i ++) + data_startElement.append( + SEPARATOR_STRING +attributes.getQName(i) + + SEPARATOR_STRING + attributes.getValue(i)); + + data_isStartDocument.append(SEPARATOR_ELEMENT); + } + + @Override + public void startPrefixMapping(String prefix, String uri) { + data_startPrefixMapping.append(prefix + SEPARATOR_STRING + uri); + } + + @Override + public void unparsedEntityDecl(String name, String publicId, + String systemId, String notationName) { + // data_unparsedEntityDecl.append(name + // + ParsingSupport.SEPARATOR_STRING + publicId + // + ParsingSupport.SEPARATOR_STRING + // + systemId + ParsingSupport.SEPARATOR_STRING + notationName); + } + + @Override + public void warning(SAXParseException e) { + data_warning.append(e); + } + } + + @SuppressWarnings("deprecation") + static class MyHandler extends HandlerBase { + + public StringBuffer data_isEndDocument = new StringBuffer(); + public StringBuffer data_isStartDocument = new StringBuffer(); + public StringBuffer data_text = new StringBuffer(); + public StringBuffer data_error = new StringBuffer(); + public StringBuffer data_fatalError = new StringBuffer(); + public StringBuffer data_warning = new StringBuffer(); + public StringBuffer data_endElement = new StringBuffer(); + public StringBuffer data_endPrefixMapping = new StringBuffer(); + public StringBuffer data_processingInstruction = new StringBuffer(); + public StringBuffer data_skippedEntity = new StringBuffer(); + public StringBuffer data_startElement = new StringBuffer(); + public StringBuffer data_startPrefixMapping = new StringBuffer(); + + public void printMap() { + System.out.print(data_isStartDocument.toString() + SEPARATOR_DATA + + data_isEndDocument.toString() + SEPARATOR_DATA + + data_text.toString() + SEPARATOR_DATA + + data_error.toString()+ SEPARATOR_DATA + + data_fatalError.toString()+ SEPARATOR_DATA + + data_warning.toString()+ SEPARATOR_DATA + + data_endElement.toString() + SEPARATOR_DATA+ + data_endPrefixMapping.toString()+ SEPARATOR_DATA + + data_processingInstruction.toString() + SEPARATOR_DATA + + data_skippedEntity.toString() + SEPARATOR_DATA + + data_startElement.toString() + SEPARATOR_DATA + + data_startPrefixMapping.toString()+ SEPARATOR_DATA); + } + + public HashMap<String, String> createData() { + HashMap<String, String> hm = new HashMap<String, String>(); + hm.put(KEY_IS_END_DOC, data_isEndDocument.toString()); + hm.put(KEY_IS_START_DOC, data_isStartDocument.toString()); + hm.put(KEY_TEXT, data_text.toString()); + hm.put(KEY_ERROR, data_error.toString()); + hm.put(KEY_FATAL_ERROR, data_fatalError.toString()); + hm.put(KEY_WARNING, data_warning.toString()); + hm.put(KEY_END_ELEMENT, data_endElement.toString()); + hm.put(KEY_END_PREFIX_MAPPING, data_endPrefixMapping.toString()); + hm.put(KEY_PROCESSING_INSTRUCTION, + data_processingInstruction.toString()); + hm.put(KEY_SKIPPED_ENTITY, data_skippedEntity.toString()); + hm.put(KEY_START_ELEMENT, data_startElement.toString()); + hm.put(KEY_START_PREFIX_MAPPING, + data_startPrefixMapping.toString()); + return hm; + } + + @Override + public void characters(char[] ch, int start, int length) { + String str = new String(ch, start, length); + data_text.append(str); + // different sax parsers are allowed to handle chunking differently, + // therefore we cannot rely on identical chunks being delivered. + //data_text.append(ParsingSupport.SEPARATOR_ELEMENT); + } + + @Override + public void endDocument() { + data_isEndDocument.append(true); + data_isEndDocument.append(SEPARATOR_ELEMENT); + } + + public void endElement(String uri, String localName, String qName) { + StringBuffer sb = new StringBuffer(); + sb.append(uri); + sb.append(SEPARATOR_STRING); + sb.append(localName); + sb.append(SEPARATOR_STRING); + sb.append(qName); + data_endElement.append(sb); + data_endElement.append(SEPARATOR_ELEMENT); + } + + @Override + public void error(SAXParseException e) { + data_error.append(e); + data_error.append(SEPARATOR_ELEMENT); + } + + @Override + public void fatalError(SAXParseException e) { + data_fatalError.append(e); + data_fatalError.append(SEPARATOR_ELEMENT); + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) { + + } + + @Override + public void notationDecl(String name, String publicId, + String systemId) { + + } + + @Override + public void processingInstruction(String target, String data) { + data_processingInstruction.append(target + SEPARATOR_STRING + data); + data_processingInstruction.append(SEPARATOR_ELEMENT); + } + + @Override + public InputSource resolveEntity(String publicId, String systemId) { + return null; + } + + @Override + public void setDocumentLocator(Locator locator) { + + } + + @Override + public void startDocument() { + data_isStartDocument.append(true); + data_isStartDocument.append(SEPARATOR_ELEMENT); + } + + public void startElement(String uri, String localName, String qName, + Attributes attributes) { + data_startElement.append(uri); + data_startElement.append(SEPARATOR_STRING); + data_startElement.append(localName); + data_startElement.append(SEPARATOR_STRING); + data_startElement.append(qName); + + for(int i = 0; i < attributes.getLength(); i ++) + data_startElement.append(SEPARATOR_STRING + + attributes.getQName(i) + + SEPARATOR_STRING + attributes.getValue(i)); + + data_isStartDocument.append(SEPARATOR_ELEMENT); + } + + @Override + public void unparsedEntityDecl(String name, String publicId, + String systemId, String notationName) { + + } + + @Override + public void warning(SAXParseException e) { + data_warning.append(e); + } + } +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/AllTests.java b/xml/src/test/java/tests/api/org/xml/sax/AllTests.java new file mode 100644 index 0000000..9c29178 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/AllTests.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AllTests { + + public static void main(String[] args) { + junit.textui.TestRunner.run(AllTests.suite()); + } + + public static Test suite() { + TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for org.xml.sax package"); + // $JUnit-BEGIN$ + + suite.addTestSuite(HandlerBaseTest.class); + suite.addTestSuite(InputSourceTest.class); + suite.addTestSuite(SAXExceptionTest.class); + suite.addTestSuite(SAXNotRecognizedExceptionTest.class); + suite.addTestSuite(SAXNotSupportedExceptionTest.class); + suite.addTestSuite(SAXParseExceptionTest.class); + + suite.addTest(tests.api.org.xml.sax.ext.AllTests.suite()); + suite.addTest(tests.api.org.xml.sax.helpers.AllTests.suite()); + + // $JUnit-END$ + return suite; + } +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/HandlerBaseTest.java b/xml/src/test/java/tests/api/org/xml/sax/HandlerBaseTest.java new file mode 100644 index 0000000..7c7f591 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/HandlerBaseTest.java @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +import junit.framework.TestCase; + +import org.xml.sax.AttributeList; +import org.xml.sax.HandlerBase; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.AttributeListImpl; +import org.xml.sax.helpers.LocatorImpl; + +@SuppressWarnings("deprecation") +@TestTargetClass(HandlerBase.class) +public class HandlerBaseTest extends TestCase { + + /* + * Note: most of the tests have to check for an empty implementation of the + * respective methods and, as a result, are somewhat trivial. + */ + + private HandlerBase h = new HandlerBase(); + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "resolveEntity", + args = { String.class, String.class } + ) + public void testResolveEntity() { + try { + h.resolveEntity("publicID", "systemID"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "notationDecl", + args = { String.class, String.class, String.class } + ) + public void testNotationDecl() { + h.notationDecl("name", "publicID", "systemID"); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "unparsedEntityDecl", + args = { String.class, String.class, String.class, String.class } + ) + public void testUnparsedEntityDecl() { + h.unparsedEntityDecl("name", "publicID", "systemID", "notationName"); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDocumentLocator", + args = { org.xml.sax.Locator.class } + ) + public void testSetDocumentLocator() { + h.setDocumentLocator(new LocatorImpl()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startDocument", + args = { } + ) + public void testStartDocument() { + try { + h.startDocument(); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endDocument", + args = { } + ) + public void testEndDocument() { + try { + h.endDocument(); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startElement", + args = { String.class, AttributeList.class } + ) + public void testStartElement() { + try { + h.startElement("name", new AttributeListImpl()); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endElement", + args = { String.class } + ) + public void testEndElement() { + try { + h.endElement("name"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "characters", + args = { char[].class, int.class, int.class } + ) + public void testCharacters() { + try { + h.characters("The quick brown fox".toCharArray(), 4, 11); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "ignorableWhitespace", + args = { char[].class, int.class, int.class } + ) + public void testIgnorableWhitespace() { + try { + h.ignorableWhitespace(" ".toCharArray(), 4, 11); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "processingInstruction", + args = { String.class, String.class } + ) + public void testProcessingInstruction() { + try { + h.processingInstruction("target", "data"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "warning", + args = { org.xml.sax.SAXParseException.class } + ) + public void testWarning() { + try { + h.warning(new SAXParseException("Foo", new LocatorImpl())); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "error", + args = { org.xml.sax.SAXParseException.class } + ) + public void testError() { + try { + h.error(new SAXParseException("Foo", new LocatorImpl())); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "fatalError", + args = { org.xml.sax.SAXParseException.class } + ) + public void testFatalError() { + // Ordinary case + try { + h.fatalError(new SAXParseException("Foo", new LocatorImpl())); + fail("SAXException expected"); + } catch (SAXException e) { + // Expected + } + + // No exception + try { + h.fatalError(null); + fail("NullPointerException expected"); + } catch (SAXException e) { + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/InputSourceTest.java b/xml/src/test/java/tests/api/org/xml/sax/InputSourceTest.java new file mode 100644 index 0000000..7c73b52 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/InputSourceTest.java @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; + +import junit.framework.TestCase; + +import org.xml.sax.InputSource; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@TestTargetClass(InputSource.class) +public class InputSourceTest extends TestCase { + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "InputSource", + args = { } + ) + public void testInputSource() { + InputSource i = new InputSource(); + + assertNull(i.getByteStream()); + assertNull(i.getCharacterStream()); + assertNull(i.getEncoding()); + assertNull(i.getPublicId()); + assertNull(i.getSystemId()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "InputSource", + args = { String.class } + ) + public void testInputSourceString() { + InputSource i = new InputSource("Foo"); + + assertNull(i.getByteStream()); + assertNull(i.getCharacterStream()); + assertNull(i.getEncoding()); + assertNull(i.getPublicId()); + assertEquals("Foo", i.getSystemId()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "InputSource", + args = { InputStream.class } + ) + public void testInputSourceInputStream() { + ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]); + + // Ordinary case + InputSource i = new InputSource(bais); + + assertEquals(bais, i.getByteStream()); + assertNull(i.getCharacterStream()); + assertNull(i.getEncoding()); + assertNull(i.getPublicId()); + assertNull(i.getSystemId()); + + // No input stream + i = new InputSource((InputStream)null); + + assertNull(i.getByteStream()); + assertNull(i.getCharacterStream()); + assertNull(i.getEncoding()); + assertNull(i.getPublicId()); + assertNull(i.getSystemId()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "InputSource", + args = { Reader.class } + ) + public void testInputSourceReader() { + StringReader sr = new StringReader("Hello, world."); + + // Ordinary case + InputSource i = new InputSource(sr); + + assertNull(i.getByteStream()); + assertEquals(sr, i.getCharacterStream()); + assertNull(i.getEncoding()); + assertNull(i.getPublicId()); + assertNull(i.getSystemId()); + + // No reader + i = new InputSource((Reader)null); + + assertNull(i.getByteStream()); + assertNull(i.getCharacterStream()); + assertNull(i.getEncoding()); + assertNull(i.getPublicId()); + assertNull(i.getSystemId()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setPublicId", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getPublicId", + args = { } + ) + }) + public void testSetPublicIdGetPublicId() { + InputSource i = new InputSource(); + + i.setPublicId("Foo"); + assertEquals("Foo", i.getPublicId()); + + i.setPublicId(null); + assertNull(i.getPublicId()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setSystemId", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getSystemId", + args = { } + ) + }) + public void testSetSystemIdGetSystemId() { + InputSource i = new InputSource(); + + i.setSystemId("Foo"); + assertEquals("Foo", i.getSystemId()); + + i.setSystemId(null); + assertNull(i.getSystemId()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setByteStream", + args = { InputStream.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getByteStream", + args = { } + ) + }) + public void testSetByteStreamGetByteStream() { + ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]); + + InputSource i = new InputSource(); + + // Ordinary case + i.setByteStream(bais); + + assertEquals(bais, i.getByteStream()); + + // No input stream + i.setByteStream(null); + + assertNull(i.getByteStream()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setEncoding", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getEncoding", + args = { } + ) + }) + public void testSetEncodingGetEncoding() { + InputSource i = new InputSource(); + + // Ordinary case + i.setEncoding("Klingon"); + + assertEquals("Klingon", i.getEncoding()); + + // No encoding + i.setEncoding(null); + + assertNull(i.getEncoding()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setCharacterStream", + args = { Reader.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getCharacterStream", + args = { } + ) + }) + public void testSetCharacterStreamGetCharacterStream() { + StringReader sr = new StringReader("Hello, world."); + + InputSource i = new InputSource(); + + // Ordinary case + i.setCharacterStream(sr); + + assertNull(i.getByteStream()); + assertEquals(sr, i.getCharacterStream()); + assertNull(i.getEncoding()); + assertNull(i.getPublicId()); + assertNull(i.getSystemId()); + + // No reader + i.setCharacterStream(null); + + assertNull(i.getByteStream()); + assertNull(i.getCharacterStream()); + assertNull(i.getEncoding()); + assertNull(i.getPublicId()); + assertNull(i.getSystemId()); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/SAXExceptionTest.java b/xml/src/test/java/tests/api/org/xml/sax/SAXExceptionTest.java new file mode 100644 index 0000000..afc1f8d --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/SAXExceptionTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax; + +import junit.framework.TestCase; + +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@TestTargetClass(SAXException.class) +public class SAXExceptionTest extends TestCase { + + public static final String ERR = "Houston, we have a problem"; + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXException", + args = { } + ) + public void testSAXParseException() { + SAXException e = new SAXException(); + + assertNull(e.getMessage()); + assertNull(e.getException()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXException", + args = { String.class, Exception.class } + ) + public void testSAXException_String_Exception() { + Exception c = new Exception(); + + // Ordinary case + SAXException e = new SAXException(ERR, c); + + assertEquals(ERR, e.getMessage()); + assertEquals(c, e.getException()); + + // No message + e = new SAXException(null, c); + + assertNull(e.getMessage()); + assertEquals(c, e.getException()); + + // No cause + e = new SAXParseException(ERR, null); + + assertEquals(ERR, e.getMessage()); + assertNull(e.getException()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXException", + args = { String.class } + ) + public void testSAXException_String() { + // Ordinary case + SAXException e = new SAXException(ERR); + + assertEquals(ERR, e.getMessage()); + assertNull(e.getException()); + + // No message + e = new SAXException((String)null); + + assertNull(e.getMessage()); + assertNull(e.getException()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXException", + args = { Exception.class } + ) + public void testSAXException_Exception() { + Exception c = new Exception(); + + // Ordinary case + SAXException e = new SAXException(c); + + assertNull(e.getMessage()); + assertEquals(c, e.getException()); + + // No cause + e = new SAXException((Exception)null); + + assertNull(e.getMessage()); + assertNull(e.getException()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "toString", + args = { } + ) + public void testToString() { + // Ordinary case + SAXException e = new SAXException(ERR); + String s = e.toString(); + + assertTrue(s.contains(ERR)); + + // No message + e = new SAXException(); + s = e.toString(); + + assertFalse(s.contains(ERR)); + } + +}
\ No newline at end of file diff --git a/xml/src/test/java/tests/api/org/xml/sax/SAXNotRecognizedExceptionTest.java b/xml/src/test/java/tests/api/org/xml/sax/SAXNotRecognizedExceptionTest.java new file mode 100644 index 0000000..1fab7bf --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/SAXNotRecognizedExceptionTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax; + +import junit.framework.TestCase; + +import org.xml.sax.SAXNotRecognizedException; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@TestTargetClass(SAXNotRecognizedException.class) +public class SAXNotRecognizedExceptionTest extends TestCase { + + public static final String ERR = "Houston, we have a problem"; + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXNotRecognizedException", + args = { } + ) + public void testSAXNotRecognizedException() { + SAXNotRecognizedException e = new SAXNotRecognizedException(); + assertNull(e.getMessage()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXNotRecognizedException", + args = { String.class } + ) + public void testSAXNotRecognizedException_String() { + SAXNotRecognizedException e = new SAXNotRecognizedException(ERR); + assertEquals(ERR, e.getMessage()); + + e = new SAXNotRecognizedException(null); + assertNull(e.getMessage()); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/SAXNotSupportedExceptionTest.java b/xml/src/test/java/tests/api/org/xml/sax/SAXNotSupportedExceptionTest.java new file mode 100644 index 0000000..9060a14 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/SAXNotSupportedExceptionTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +import junit.framework.TestCase; + +import org.xml.sax.SAXNotSupportedException; + +@TestTargetClass(SAXNotSupportedException.class) +public class SAXNotSupportedExceptionTest extends TestCase { + + public static final String ERR = "Houston, we have a problem"; + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXNotSupportedException", + args = { } + ) + public void testSAXNotSupportedException() { + SAXNotSupportedException e = new SAXNotSupportedException(); + assertNull(e.getMessage()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXNotSupportedException", + args = { String.class } + ) + public void testSAXNotSupportedException_String() { + SAXNotSupportedException e = new SAXNotSupportedException(ERR); + assertEquals(ERR, e.getMessage()); + + e = new SAXNotSupportedException(null); + assertNull(e.getMessage()); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/SAXParseExceptionTest.java b/xml/src/test/java/tests/api/org/xml/sax/SAXParseExceptionTest.java new file mode 100644 index 0000000..aff0c7f --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/SAXParseExceptionTest.java @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax; + +import junit.framework.TestCase; + +import org.xml.sax.Locator; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.LocatorImpl; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@TestTargetClass(SAXParseException.class) +public class SAXParseExceptionTest extends TestCase { + + public static final String ERR = "Houston, we have a problem"; + + public static final String SYS = "mySystemID"; + + public static final String PUB = "myPublicID"; + + public static final int ROW = 1; + + public static final int COL = 2; + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXParseException", + args = { String.class, Locator.class, Exception.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getMessage", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getException", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getPublicId", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getSystemId", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getLineNumber", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getColumnNumber", + args = { } + ) + }) + public void testSAXParseException_String_Locator_Exception() { + LocatorImpl l = new LocatorImpl(); + l.setPublicId(PUB); + l.setSystemId(SYS); + l.setLineNumber(ROW); + l.setColumnNumber(COL); + + Exception c = new Exception(); + + // Ordinary case + SAXParseException e = new SAXParseException(ERR, l, c); + + assertEquals(ERR, e.getMessage()); + assertEquals(c, e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + + // No message + e = new SAXParseException(null, l, c); + + assertNull(e.getMessage()); + assertEquals(c, e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + + // No locator + e = new SAXParseException(ERR, null, c); + + assertEquals(ERR, e.getMessage()); + assertEquals(c, e.getException()); + + assertNull(e.getPublicId()); + assertNull(e.getSystemId()); + assertEquals(-1, e.getLineNumber()); + assertEquals(-1, e.getColumnNumber()); + + // No cause + e = new SAXParseException(ERR, l, null); + + assertEquals(ERR, e.getMessage()); + assertNull(e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXParseException", + args = { String.class, Locator.class } + ) + public void testSAXParseException_String_Locator() { + LocatorImpl l = new LocatorImpl(); + l.setPublicId(PUB); + l.setSystemId(SYS); + l.setLineNumber(ROW); + l.setColumnNumber(COL); + + // Ordinary case + SAXParseException e = new SAXParseException(ERR, l); + + assertEquals(ERR, e.getMessage()); + assertNull(e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + + // No message + e = new SAXParseException(null, l); + + assertNull(e.getMessage()); + assertNull(e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + + // No locator + e = new SAXParseException(ERR, null); + + assertEquals(ERR, e.getMessage()); + assertNull(e.getException()); + + assertNull(e.getPublicId()); + assertNull(e.getSystemId()); + assertEquals(-1, e.getLineNumber()); + assertEquals(-1, e.getColumnNumber()); + + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXParseException", + args = { String.class, String.class, String.class, int.class, int.class, + Exception.class } + ) + public void testSAXParseException_String_String_String_int_int_Exception() { + Exception c = new Exception(); + + // Ordinary case + SAXParseException e = new SAXParseException(ERR, PUB, SYS, ROW, COL, c); + + assertEquals(ERR, e.getMessage()); + assertEquals(c, e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + + // No message + e = new SAXParseException(null, PUB, SYS, ROW, COL, c); + + assertNull(e.getMessage()); + assertEquals(c, e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + + // No locator + e = new SAXParseException(ERR, null, null, -1, -1, c); + + assertEquals(ERR, e.getMessage()); + assertEquals(c, e.getException()); + + assertNull(e.getPublicId()); + assertNull(e.getSystemId()); + assertEquals(-1, e.getLineNumber()); + assertEquals(-1, e.getColumnNumber()); + + // No cause + e = new SAXParseException(ERR, PUB, SYS, ROW, COL, null); + + assertEquals(ERR, e.getMessage()); + assertNull(e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "SAXParseException", + args = { String.class, String.class, String.class, int.class, + int.class } + ) + public void testSAXParseException_String_String_String_int_int() { + // Ordinary case + SAXParseException e = new SAXParseException(ERR, PUB, SYS, ROW, COL); + + assertEquals(ERR, e.getMessage()); + assertNull(e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + + // No message + e = new SAXParseException(null, PUB, SYS, ROW, COL); + + assertNull(e.getMessage()); + assertNull(e.getException()); + + assertEquals(PUB, e.getPublicId()); + assertEquals(SYS, e.getSystemId()); + assertEquals(ROW, e.getLineNumber()); + assertEquals(COL, e.getColumnNumber()); + + // No locator + e = new SAXParseException(ERR, null, null, -1, -1); + + assertEquals(ERR, e.getMessage()); + assertNull(e.getException()); + + assertNull(e.getPublicId()); + assertNull(e.getSystemId()); + assertEquals(-1, e.getLineNumber()); + assertEquals(-1, e.getColumnNumber()); + } + +}
\ No newline at end of file diff --git a/xml/src/test/java/tests/api/org/xml/sax/ext/AllTests.java b/xml/src/test/java/tests/api/org/xml/sax/ext/AllTests.java new file mode 100644 index 0000000..f4b34b8 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/ext/AllTests.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.ext; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AllTests { + + public static void main(String[] args) { + junit.textui.TestRunner.run(AllTests.suite()); + } + + public static Test suite() { + TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for org.xml.sax.ext package"); + // $JUnit-BEGIN$ + + suite.addTestSuite(Attributes2ImplTest.class); + suite.addTestSuite(DefaultHandler2Test.class); + suite.addTestSuite(Locator2ImplTest.class); + + // $JUnit-END$ + return suite; + } +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/ext/Attributes2ImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/ext/Attributes2ImplTest.java new file mode 100644 index 0000000..9ccdc8a --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/ext/Attributes2ImplTest.java @@ -0,0 +1,464 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.ext; + +import junit.framework.TestCase; + +import org.xml.sax.Attributes; +import org.xml.sax.ext.Attributes2Impl; +import org.xml.sax.helpers.AttributesImpl; + +import dalvik.annotation.KnownFailure; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@TestTargetClass(Attributes2Impl.class) +public class Attributes2ImplTest extends TestCase { + + // Note: The original SAX2 implementation of Attributes2Impl is + // severely broken. Thus all of these tests will probably fail + // unless the Android implementation of the class gets fixed. + + private Attributes2Impl empty = new Attributes2Impl(); + + private Attributes2Impl multi = new Attributes2Impl(); + + private Attributes2Impl cdata = new Attributes2Impl(); + + @Override + public void setUp() { + multi.addAttribute("http://some.uri", "foo", "ns1:foo", + "string", "abc"); + multi.addAttribute("http://some.uri", "bar", "ns1:bar", + "string", "xyz"); + multi.addAttribute("http://some.other.uri", "answer", "ns2:answer", + "int", "42"); + multi.addAttribute("http://yet.another.uri", "gabba", "ns3:gabba", + "string", "gabba"); + + multi.setDeclared(0, false); + multi.setSpecified(0, false); + + multi.setDeclared(1, true); + multi.setSpecified(1, false); + + multi.setDeclared(2, false); + multi.setSpecified(2, true); + + multi.setDeclared(3, true); + multi.setSpecified(3, true); + + cdata.addAttribute("http://yet.another.uri", "hey", "ns3:hey", + "CDATA", "hey"); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setAttributes", + args = { Attributes.class } + ) + public void testSetAttributes() { + // Ordinary case with Attributes2Impl + Attributes2Impl attrs = new Attributes2Impl(); + attrs.addAttribute("", "", "john", "string", "doe"); + + attrs.setAttributes(empty); + assertEquals(0, attrs.getLength()); + + attrs.setAttributes(multi); + for (int i = 0; i < multi.getLength(); i++) { + assertEquals(multi.getURI(i), attrs.getURI(i)); + assertEquals(multi.getLocalName(i), attrs.getLocalName(i)); + assertEquals(multi.getQName(i), attrs.getQName(i)); + assertEquals(multi.getType(i), attrs.getType(i)); + assertEquals(multi.getValue(i), attrs.getValue(i)); + assertEquals(multi.isDeclared(i), attrs.isDeclared(i)); + assertEquals(multi.isSpecified(i), attrs.isSpecified(i)); + } + + attrs.setAttributes(empty); + assertEquals(0, attrs.getLength()); + + // Ordinary case with AttributesImpl + attrs.setAttributes(new AttributesImpl(multi)); + assertEquals(multi.getLength(), attrs.getLength()); + + for (int i = 0; i < multi.getLength(); i++) { + assertEquals(multi.getURI(i), attrs.getURI(i)); + assertEquals(multi.getLocalName(i), attrs.getLocalName(i)); + assertEquals(multi.getQName(i), attrs.getQName(i)); + assertEquals(multi.getType(i), attrs.getType(i)); + assertEquals(multi.getValue(i), attrs.getValue(i)); + assertEquals(true, attrs.isDeclared(i)); + assertEquals(true, attrs.isSpecified(i)); + } + + // Special case with CDATA + attrs.setAttributes(new AttributesImpl(cdata)); + assertEquals(1, attrs.getLength()); + assertEquals(false, attrs.isDeclared(0)); + assertEquals(true, attrs.isSpecified(0)); + + // null case + try { + attrs.setAttributes(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "addAttribute", + args = { String.class, String.class, String.class, String.class, + String.class } + ) + public void testAddAttribute() { + Attributes2Impl attrs = new Attributes2Impl(); + + // Ordinary case + attrs.addAttribute("http://yet.another.uri", "doe", "john:doe", + "string", "abc"); + + assertEquals(1, attrs.getLength()); + + assertEquals("http://yet.another.uri", attrs.getURI(0)); + assertEquals("doe", attrs.getLocalName(0)); + assertEquals("john:doe", attrs.getQName(0)); + assertEquals("string", attrs.getType(0)); + assertEquals("abc", attrs.getValue(0)); + + assertEquals(true, attrs.isDeclared(0)); + assertEquals(true, attrs.isSpecified(0)); + + // CDATA case + attrs.addAttribute("http://yet.another.uri", "doe", "jane:doe", + "CDATA", "abc"); + + assertEquals(2, attrs.getLength()); + + assertEquals("http://yet.another.uri", attrs.getURI(1)); + assertEquals("doe", attrs.getLocalName(1)); + assertEquals("jane:doe", attrs.getQName(1)); + assertEquals("CDATA", attrs.getType(1)); + assertEquals("abc", attrs.getValue(1)); + + assertEquals(false, attrs.isDeclared(1)); + assertEquals(true, attrs.isSpecified(1)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "removeAttribute", + args = { int.class } + ) + public void testRemoveAttribute() { + Attributes2Impl attrs = new Attributes2Impl(multi); + + // Ordinary case + attrs.removeAttribute(1); + + assertEquals(3, attrs.getLength()); + + assertEquals(multi.getURI(0), attrs.getURI(0)); + assertEquals(multi.getLocalName(0), attrs.getLocalName(0)); + assertEquals(multi.getQName(0), attrs.getQName(0)); + assertEquals(multi.getType(0), attrs.getType(0)); + assertEquals(multi.getValue(0), attrs.getValue(0)); + assertEquals(multi.isDeclared(0), attrs.isDeclared(0)); + assertEquals(multi.isSpecified(0), attrs.isSpecified(0)); + + assertEquals(multi.getURI(2), attrs.getURI(1)); + assertEquals(multi.getLocalName(2), attrs.getLocalName(1)); + assertEquals(multi.getQName(2), attrs.getQName(1)); + assertEquals(multi.getType(2), attrs.getType(1)); + assertEquals(multi.getValue(2), attrs.getValue(1)); + assertEquals(multi.isDeclared(2), attrs.isDeclared(1)); + assertEquals(multi.isSpecified(2), attrs.isSpecified(1)); + + // Out of range + try { + attrs.removeAttribute(-1); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + attrs.removeAttribute(3); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "Attributes2Impl", + args = { } + ) + public void testAttributes2Impl() { + assertEquals(0, empty.getLength()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "Attributes2Impl", + args = { Attributes.class } + ) + public void testAttributes2ImplAttributes() { + // Ordinary case with Attributes2Impl + Attributes2Impl attrs = new Attributes2Impl(multi); + assertEquals(multi.getLength(), attrs.getLength()); + + for (int i = 0; i < multi.getLength(); i++) { + assertEquals(multi.getURI(i), attrs.getURI(i)); + assertEquals(multi.getLocalName(i), attrs.getLocalName(i)); + assertEquals(multi.getQName(i), attrs.getQName(i)); + assertEquals(multi.getType(i), attrs.getType(i)); + assertEquals(multi.getValue(i), attrs.getValue(i)); + assertEquals(multi.isDeclared(i), attrs.isDeclared(i)); + assertEquals(multi.isSpecified(i), attrs.isSpecified(i)); + } + + attrs = new Attributes2Impl(empty); + assertEquals(0, attrs.getLength()); + + // Ordinary case with AttributesImpl + attrs = new Attributes2Impl(new AttributesImpl(multi)); + assertEquals(multi.getLength(), attrs.getLength()); + + for (int i = 0; i < multi.getLength(); i++) { + assertEquals(multi.getURI(i), attrs.getURI(i)); + assertEquals(multi.getLocalName(i), attrs.getLocalName(i)); + assertEquals(multi.getQName(i), attrs.getQName(i)); + assertEquals(multi.getType(i), attrs.getType(i)); + assertEquals(multi.getValue(i), attrs.getValue(i)); + assertEquals(true, attrs.isDeclared(i)); + assertEquals(true, attrs.isSpecified(i)); + } + + // Special case with CDATA + attrs = new Attributes2Impl(new AttributesImpl(cdata)); + assertEquals(1, attrs.getLength()); + assertEquals(false, attrs.isDeclared(0)); + assertEquals(true, attrs.isSpecified(0)); + + // null case + try { + attrs = new Attributes2Impl(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "isDeclared", + args = { int.class } + ) + public void testIsDeclaredInt() { + // Ordinary cases + assertEquals(false, multi.isDeclared(0)); + assertEquals(true, multi.isDeclared(1)); + + // Out of range + try { + multi.isDeclared(-1); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.isDeclared(4); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "isDeclared", + args = { String.class, String.class } + ) + public void testIsDeclaredStringString() { + // Ordinary cases + assertEquals(false, multi.isDeclared("http://some.uri", "foo")); + assertEquals(true, multi.isDeclared("http://some.uri", "bar")); + + // Not found + try { + assertFalse(multi.isDeclared("not", "found")); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "isDeclared", + args = { String.class } + ) + public void testIsDeclaredString() { + // Ordinary cases + assertEquals(false, multi.isDeclared("ns1:foo")); + assertEquals(true, multi.isDeclared("ns1:bar")); + + // Not found + try { + assertFalse(multi.isDeclared("notfound")); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "isSpecified", + args = { int.class } + ) + public void testIsSpecifiedInt() { + // Ordinary cases + assertEquals(false, multi.isSpecified(1)); + assertEquals(true, multi.isSpecified(2)); + + // Out of range + try { + multi.isSpecified(-1); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.isSpecified(4); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "isSpecified", + args = { String.class, String.class } + ) + public void testIsSpecifiedStringString() { + // Ordinary cases + assertEquals(false, multi.isSpecified("http://some.uri", "bar")); + assertEquals(true, multi.isSpecified("http://some.other.uri", "answer")); + + // Not found + try { + assertFalse(multi.isSpecified("not", "found")); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "isSpecified", + args = { String.class } + ) + public void testIsSpecifiedString() { + // Ordinary cases + assertEquals(false, multi.isSpecified("ns1:bar")); + assertEquals(true, multi.isSpecified("ns2:answer")); + + // Not found + try { + assertFalse(multi.isSpecified("notfound")); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDeclared", + args = { int.class, boolean.class } + ) + public void testSetDeclared() { + // Ordinary cases + multi.setSpecified(0, false); + assertEquals(false, multi.isSpecified(0)); + + multi.setSpecified(0, true); + assertEquals(true, multi.isSpecified(0)); + + multi.setSpecified(0, false); + assertEquals(false, multi.isSpecified(0)); + + // Out of range + try { + multi.setSpecified(-1, true); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.setSpecified(5, true); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setSpecified", + args = { int.class, boolean.class } + ) + public void testSetSpecified() { + // Ordinary cases + multi.setSpecified(0, false); + assertEquals(false, multi.isSpecified(0)); + + multi.setSpecified(0, true); + assertEquals(true, multi.isSpecified(0)); + + multi.setSpecified(0, false); + assertEquals(false, multi.isSpecified(0)); + + // Out of range + try { + multi.setSpecified(-1, true); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.setSpecified(5, true); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/ext/DefaultHandler2Test.java b/xml/src/test/java/tests/api/org/xml/sax/ext/DefaultHandler2Test.java new file mode 100644 index 0000000..52a5972 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/ext/DefaultHandler2Test.java @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.ext; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +import junit.framework.TestCase; + +import org.xml.sax.SAXException; +import org.xml.sax.ext.DefaultHandler2; + +import java.io.IOException; + +@TestTargetClass(DefaultHandler2.class) +public class DefaultHandler2Test extends TestCase { + + private DefaultHandler2 h = new DefaultHandler2(); + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "DefaultHandler2", + args = { } + ) + public void testDefaultHandler2() { + new DefaultHandler2(); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startCDATA", + args = { } + ) + public void testStartCDATA() { + try { + h.startCDATA(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endCDATA", + args = { } + ) + public void testEndCDATA() { + try { + h.endCDATA(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startDTD", + args = { String.class, String.class, String.class } + ) + public void testStartDTD() { + try { + h.startDTD("name", "publicId", "systemId"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endDTD", + args = { } + ) + public void testEndDTD() { + try { + h.endDTD(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startEntity", + args = { String.class } + ) + public void testStartEntity() { + try { + h.startEntity("name"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endEntity", + args = { String.class } + ) + public void testEndEntity() { + try { + h.endEntity("name"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "comment", + args = { char[].class, int.class, int.class } + ) + public void testComment() { + try { + h.comment("<!-- Comment -->".toCharArray(), 0, 15); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "attributeDecl", + args = { String.class, String.class, String.class, String.class, + String.class } + ) + public void testAttributeDecl() { + try { + h.attributeDecl("eName", "aName", "type", "mode", "value"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "elementDecl", + args = { String.class, String.class } + ) + public void testElementDecl() { + try { + h.elementDecl("name", "model"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "externalEntityDecl", + args = { String.class, String.class, String.class } + ) + public void testExternalEntityDecl() { + try { + h.externalEntityDecl("name", "publicId", "systemId"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "internalEntityDecl", + args = { String.class, String.class } + ) + public void testInternalEntityDecl() { + try { + h.internalEntityDecl("name", "value"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getExternalSubset", + args = { String.class, String.class } + ) + public void testGetExternalSubset() { + try { + assertNull(h.getExternalSubset("name", "http://some.uri")); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "resolveEntity", + args = { String.class, String.class } + ) + public void testResolveEntityStringString() { + try { + assertNull(h.resolveEntity("publicId", "systemId")); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "resolveEntity", + args = { String.class, String.class, String.class, String.class } + ) + public void testResolveEntityStringStringStringString() { + try { + assertNull(h.resolveEntity("name", "publicId", "http://some.uri", + "systemId")); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/ext/Locator2ImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/ext/Locator2ImplTest.java new file mode 100644 index 0000000..b018f59 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/ext/Locator2ImplTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.ext; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +import junit.framework.TestCase; + +import org.xml.sax.Locator; +import org.xml.sax.ext.Locator2Impl; +import org.xml.sax.helpers.LocatorImpl; + +@TestTargetClass(Locator2Impl.class) +public class Locator2ImplTest extends TestCase { + + public static final String SYS = "mySystemID"; + + public static final String PUB = "myPublicID"; + + public static final int ROW = 1; + + public static final int COL = 2; + + public static final String ENC = "Klingon"; + + public static final String XML = "1.0"; + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "Locator2Impl", + args = { } + ) + public void testLocatorImpl() { + Locator2Impl l = new Locator2Impl(); + + assertEquals(null, l.getPublicId()); + assertEquals(null, l.getSystemId()); + assertEquals(0, l.getLineNumber()); + assertEquals(0, l.getColumnNumber()); + + assertEquals(null, l.getEncoding()); + assertEquals(null, l.getXMLVersion()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "Locator2Impl", + args = { Locator.class } + ) + public void testLocatorImplLocator() { + Locator2Impl inner = new Locator2Impl(); + + inner.setPublicId(PUB); + inner.setSystemId(SYS); + inner.setLineNumber(ROW); + inner.setColumnNumber(COL); + + inner.setEncoding(ENC); + inner.setXMLVersion(XML); + + // Ordinary case + Locator2Impl outer = new Locator2Impl(inner); + + assertEquals(PUB, outer.getPublicId()); + assertEquals(SYS, outer.getSystemId()); + assertEquals(ROW, outer.getLineNumber()); + assertEquals(COL, outer.getColumnNumber()); + + assertEquals(ENC, outer.getEncoding()); + assertEquals(XML, outer.getXMLVersion()); + + // Instance of old locator + outer = new Locator2Impl(new LocatorImpl(inner)); + + assertEquals(PUB, outer.getPublicId()); + assertEquals(SYS, outer.getSystemId()); + assertEquals(ROW, outer.getLineNumber()); + assertEquals(COL, outer.getColumnNumber()); + + assertEquals(null, outer.getEncoding()); + assertEquals(null, outer.getXMLVersion()); + + // No locator + try { + outer = new Locator2Impl(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setXMLVersion", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getXMLVersion", + args = { } + ) + }) + public void testSetXMLVersionGetXMLVersion() { + Locator2Impl l = new Locator2Impl(); + + l.setXMLVersion(XML); + assertEquals(XML, l.getXMLVersion()); + + l.setXMLVersion(null); + assertEquals(null, l.getXMLVersion()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setEncoding", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getEncoding", + args = { } + ) + }) + public void testSetEncodingGetEncoding() { + Locator2Impl l = new Locator2Impl(); + + l.setEncoding(ENC); + assertEquals(ENC, l.getEncoding()); + + l.setEncoding(null); + assertEquals(null, l.getEncoding()); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/AllTests.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/AllTests.java new file mode 100644 index 0000000..5bf63bf --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/AllTests.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AllTests { + + public static void main(String[] args) { + junit.textui.TestRunner.run(AllTests.suite()); + } + + public static Test suite() { + TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for org.xml.sax.helpers package"); + // $JUnit-BEGIN$ + + suite.addTestSuite(AttributeListImplTest.class); + suite.addTestSuite(AttributesImplTest.class); + suite.addTestSuite(ParserFactoryTest.class); + suite.addTestSuite(DefaultHandlerTest.class); + suite.addTestSuite(LocatorImplTest.class); + suite.addTestSuite(NamespaceSupportTest.class); + suite.addTestSuite(XMLFilterImplTest.class); + suite.addTestSuite(XMLReaderAdapterTest.class); + suite.addTestSuite(XMLReaderFactoryTest.class); + + // $JUnit-END$ + return suite; + } +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributeListImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributeListImplTest.java new file mode 100644 index 0000000..00658cb --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributeListImplTest.java @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import junit.framework.TestCase; + +import org.xml.sax.AttributeList; +import org.xml.sax.helpers.AttributeListImpl; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@SuppressWarnings("deprecation") +@TestTargetClass(AttributeListImpl.class) +public class AttributeListImplTest extends TestCase { + + private AttributeListImpl empty = new AttributeListImpl(); + + private AttributeListImpl multi = new AttributeListImpl(); + + @Override + public void setUp() { + multi.addAttribute("foo", "string", "abc"); + multi.addAttribute("bar", "string", "xyz"); + multi.addAttribute("answer", "int", "42"); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "AttributeListImpl", + args = { } + ) + public void testAttributeListImpl() { + assertEquals(0, empty.getLength()); + assertEquals(3, multi.getLength()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "AttributeListImpl", + args = { AttributeList.class } + ) + public void testAttributeListImplAttributeList() { + // Ordinary case + AttributeListImpl ai = new AttributeListImpl(empty); + assertEquals(0, ai.getLength()); + + // Another ordinary case + ai = new AttributeListImpl(multi); + assertEquals(3, ai.getLength()); + + // No Attributes + try { + ai = new AttributeListImpl(null); + assertEquals(0, ai.getLength()); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setAttributeList", + args = { AttributeList.class } + ) + public void testSetAttributeList() { + // Ordinary cases + AttributeListImpl attrs = new AttributeListImpl(); + attrs.addAttribute("doe", "boolean", "false"); + + attrs.setAttributeList(empty); + assertEquals(0, attrs.getLength()); + + attrs.setAttributeList(multi); + assertEquals(multi.getLength(), attrs.getLength()); + + for (int i = 0; i < multi.getLength(); i++) { + assertEquals(multi.getName(i), attrs.getName(i)); + assertEquals(multi.getType(i), attrs.getType(i)); + assertEquals(multi.getValue(i), attrs.getValue(i)); + } + + // null case + try { + attrs.setAttributeList(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected, must still have old elements + assertEquals(3, attrs.getLength()); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "addAttribute", + args = { String.class, String.class, String.class } + ) + public void testAddAttribute() { + // Ordinary case + multi.addAttribute("doe", "boolean", "false"); + + assertEquals("doe", multi.getName(3)); + assertEquals("boolean", multi.getType(3)); + assertEquals("false", multi.getValue(3)); + + // Duplicate case + multi.addAttribute("doe", "boolean", "false"); + + assertEquals("doe", multi.getName(4)); + assertEquals("boolean", multi.getType(4)); + assertEquals("false", multi.getValue(4)); + + // null case + multi.addAttribute(null, null, null); + assertEquals(null, multi.getName(5)); + assertEquals(null, multi.getType(5)); + assertEquals(null, multi.getValue(5)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "removeAttribute", + args = { String.class } + ) + public void testRemoveAttribute() { + // Ordinary case + multi.removeAttribute("foo"); + assertEquals("bar", multi.getName(0)); + assertEquals("string", multi.getType(0)); + assertEquals("xyz", multi.getValue(0)); + + // Unknown attribute + multi.removeAttribute("john"); + assertEquals(2, multi.getLength()); + + // null case + multi.removeAttribute(null); + assertEquals(2, multi.getLength()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "clear", + args = { } + ) + public void testClear() { + assertEquals(3, multi.getLength()); + multi.clear(); + assertEquals(0, multi.getLength()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getLength", + args = { } + ) + public void testGetLength() { + AttributeListImpl ai = new AttributeListImpl(empty); + assertEquals(0, ai.getLength()); + + ai = new AttributeListImpl(multi); + assertEquals(3, ai.getLength()); + + for (int i = 2; i >= 0; i--) { + ai.removeAttribute(ai.getName(i)); + assertEquals(i, ai.getLength()); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getName", + args = { int.class } + ) + public void testGetName() { + // Ordinary cases + assertEquals("foo", multi.getName(0)); + assertEquals("bar", multi.getName(1)); + assertEquals("answer", multi.getName(2)); + + // Out of range + assertEquals(null, multi.getName(-1)); + assertEquals(null, multi.getName(3)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getType", + args = { int.class } + ) + public void testGetTypeInt() { + // Ordinary cases + assertEquals("string", multi.getType(0)); + assertEquals("string", multi.getType(1)); + assertEquals("int", multi.getType(2)); + + // Out of range + assertEquals(null, multi.getType(-1)); + assertEquals(null, multi.getType(3)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getValue", + args = { int.class } + ) + public void testGetValueInt() { + // Ordinary cases + assertEquals("abc", multi.getValue(0)); + assertEquals("xyz", multi.getValue(1)); + assertEquals("42", multi.getValue(2)); + + // Out of range + assertEquals(null, multi.getValue(-1)); + assertEquals(null, multi.getValue(5)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getType", + args = { String.class } + ) + public void testGetTypeString() { + // Ordinary cases + assertEquals("string", multi.getType("foo")); + assertEquals("string", multi.getType("bar")); + assertEquals("int", multi.getType("answer")); + + // Not found + assertEquals(null, multi.getType("john")); + + // null case + assertEquals(null, multi.getType(null)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getValue", + args = { String.class } + ) + public void testGetValueString() { + // Ordinary cases + assertEquals("abc", multi.getValue("foo")); + assertEquals("xyz", multi.getValue("bar")); + assertEquals("42", multi.getValue("answer")); + + // Not found + assertEquals(null, multi.getValue("john")); + + // null case + assertEquals(null, multi.getValue(null)); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributesImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributesImplTest.java new file mode 100644 index 0000000..0efe25f --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributesImplTest.java @@ -0,0 +1,608 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import junit.framework.TestCase; + +import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributesImpl; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@TestTargetClass(AttributesImpl.class) +public class AttributesImplTest extends TestCase { + + private AttributesImpl empty = new AttributesImpl(); + + private AttributesImpl multi = new AttributesImpl(); + + @Override + public void setUp() { + multi.addAttribute("http://some.uri", "foo", "ns1:foo", + "string", "abc"); + multi.addAttribute("http://some.uri", "bar", "ns1:bar", + "string", "xyz"); + multi.addAttribute("http://some.other.uri", "answer", "ns2:answer", + "int", "42"); + + multi.addAttribute("", "gabbaHey", "", "string", "1-2-3-4"); + multi.addAttribute("", "", "gabba:hey", "string", "1-2-3-4"); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "AttributesImpl", + args = { } + ) + public void testAttributesImpl() { + assertEquals(0, empty.getLength()); + assertEquals(5, multi.getLength()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "AttributesImpl", + args = { Attributes.class } + ) + public void testAttributesImplAttributes() { + // Ordinary case + AttributesImpl ai = new AttributesImpl(empty); + assertEquals(0, ai.getLength()); + + // Another ordinary case + ai = new AttributesImpl(multi); + assertEquals(5, ai.getLength()); + + // No Attributes + try { + ai = new AttributesImpl(null); + assertEquals(0, ai.getLength()); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getLength", + args = { } + ) + public void testGetLength() { + AttributesImpl ai = new AttributesImpl(empty); + assertEquals(0, ai.getLength()); + + ai = new AttributesImpl(multi); + assertEquals(5, ai.getLength()); + + for (int i = 4; i >= 0; i--) { + ai.removeAttribute(i); + assertEquals(i, ai.getLength()); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getURI", + args = { int.class } + ) + public void testGetURI() { + // Ordinary cases + assertEquals("http://some.uri", multi.getURI(0)); + assertEquals("http://some.uri", multi.getURI(1)); + assertEquals("http://some.other.uri", multi.getURI(2)); + assertEquals("", multi.getURI(3)); + assertEquals("", multi.getURI(4)); + + // Out of range + assertEquals(null, multi.getURI(-1)); + assertEquals(null, multi.getURI(5)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getLocalName", + args = { int.class } + ) + public void testGetLocalName() { + // Ordinary cases + assertEquals("foo", multi.getLocalName(0)); + assertEquals("bar", multi.getLocalName(1)); + assertEquals("answer", multi.getLocalName(2)); + assertEquals("gabbaHey", multi.getLocalName(3)); + assertEquals("", multi.getLocalName(4)); + + // Out of range + assertEquals(null, multi.getLocalName(-1)); + assertEquals(null, multi.getLocalName(5)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getQName", + args = { int.class } + ) + public void testGetQName() { + // Ordinary cases + assertEquals("ns1:foo", multi.getQName(0)); + assertEquals("ns1:bar", multi.getQName(1)); + assertEquals("ns2:answer", multi.getQName(2)); + assertEquals("", multi.getQName(3)); + assertEquals("gabba:hey", multi.getQName(4)); + + // Out of range + assertEquals(null, multi.getQName(-1)); + assertEquals(null, multi.getQName(5)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getType", + args = { int.class } + ) + public void testGetTypeInt() { + // Ordinary cases + assertEquals("string", multi.getType(0)); + assertEquals("string", multi.getType(1)); + assertEquals("int", multi.getType(2)); + assertEquals("string", multi.getType(3)); + assertEquals("string", multi.getType(4)); + + // Out of range + assertEquals(null, multi.getType(-1)); + assertEquals(null, multi.getType(5)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getValue", + args = { int.class } + ) + public void testGetValueInt() { + // Ordinary cases + assertEquals("abc", multi.getValue(0)); + assertEquals("xyz", multi.getValue(1)); + assertEquals("42", multi.getValue(2)); + assertEquals("1-2-3-4", multi.getValue(3)); + assertEquals("1-2-3-4", multi.getValue(4)); + + // Out of range + assertEquals(null, multi.getValue(-1)); + assertEquals(null, multi.getValue(5)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getIndex", + args = { String.class, String.class } + ) + public void testGetIndexStringString() { + // Ordinary cases + assertEquals(0, multi.getIndex("http://some.uri", "foo")); + assertEquals(1, multi.getIndex("http://some.uri", "bar")); + assertEquals(2, multi.getIndex("http://some.other.uri", "answer")); + + // Not found + assertEquals(-1, multi.getIndex("john", "doe")); + + // null cases + assertEquals(-1, multi.getIndex("http://some.uri", null)); + assertEquals(-1, multi.getIndex(null, "foo")); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getIndex", + args = { String.class } + ) + public void testGetIndexString() { + // Ordinary cases + assertEquals(0, multi.getIndex("ns1:foo")); + assertEquals(1, multi.getIndex("ns1:bar")); + assertEquals(2, multi.getIndex("ns2:answer")); + assertEquals(4, multi.getIndex("gabba:hey")); + + // Not found + assertEquals(-1, multi.getIndex("john:doe")); + + // null case + assertEquals(-1, multi.getIndex(null)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getType", + args = { String.class, String.class } + ) + public void testGetTypeStringString() { + // Ordinary cases + assertEquals("string", multi.getType("http://some.uri", "foo")); + assertEquals("string", multi.getType("http://some.uri", "bar")); + assertEquals("int", multi.getType("http://some.other.uri", "answer")); + + // Not found + assertEquals(null, multi.getType("john", "doe")); + + // null cases + assertEquals(null, multi.getType("http://some.uri", null)); + assertEquals(null, multi.getType(null, "foo")); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getType", + args = { String.class } + ) + public void testGetTypeString() { + // Ordinary cases + assertEquals("string", multi.getType("ns1:foo")); + assertEquals("string", multi.getType("ns1:bar")); + assertEquals("int", multi.getType("ns2:answer")); + assertEquals("string", multi.getType("gabba:hey")); + + // Not found + assertEquals(null, multi.getType("john:doe")); + + // null case + assertEquals(null, multi.getType(null)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getValue", + args = { String.class, String.class } + ) + public void testGetValueStringString() { + // Ordinary cases + assertEquals("abc", multi.getValue("http://some.uri", "foo")); + assertEquals("xyz", multi.getValue("http://some.uri", "bar")); + assertEquals("42", multi.getValue("http://some.other.uri", "answer")); + + // Not found + assertEquals(null, multi.getValue("john", "doe")); + + // null cases + assertEquals(null, multi.getValue("http://some.uri", null)); + assertEquals(null, multi.getValue(null, "foo")); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getValue", + args = { String.class } + ) + public void testGetValueString() { + // Ordinary cases + assertEquals("abc", multi.getValue("ns1:foo")); + assertEquals("xyz", multi.getValue("ns1:bar")); + assertEquals("42", multi.getValue("ns2:answer")); + assertEquals("1-2-3-4", multi.getValue("gabba:hey")); + + // Not found + assertEquals(null, multi.getValue("john:doe")); + + // null case + assertEquals(null, multi.getValue(null)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "clear", + args = { } + ) + public void testClear() { + assertEquals(5, multi.getLength()); + multi.clear(); + assertEquals(0, multi.getLength()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setAttributes", + args = { Attributes.class } + ) + public void testSetAttributes() { + // Ordinary cases + AttributesImpl attrs = new AttributesImpl(); + attrs.addAttribute("http://yet.another.uri", "doe", "john:doe", + "boolean", "false"); + + attrs.setAttributes(empty); + assertEquals(0, attrs.getLength()); + + attrs.setAttributes(multi); + assertEquals(multi.getLength(), attrs.getLength()); + + for (int i = 0; i < multi.getLength(); i++) { + assertEquals(multi.getURI(i), attrs.getURI(i)); + assertEquals(multi.getLocalName(i), attrs.getLocalName(i)); + assertEquals(multi.getQName(i), attrs.getQName(i)); + assertEquals(multi.getType(i), attrs.getType(i)); + assertEquals(multi.getValue(i), attrs.getValue(i)); + } + + // null case + try { + attrs.setAttributes(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected, but must be empty now + assertEquals(0, attrs.getLength()); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "addAttribute", + args = { String.class, String.class, String.class, String.class, + String.class } + ) + public void testAddAttribute() { + // Ordinary case + multi.addAttribute("http://yet.another.uri", "doe", "john:doe", + "boolean", "false"); + + assertEquals("http://yet.another.uri", multi.getURI(5)); + assertEquals("doe", multi.getLocalName(5)); + assertEquals("john:doe", multi.getQName(5)); + assertEquals("boolean", multi.getType(5)); + assertEquals("false", multi.getValue(5)); + + // Duplicate case + multi.addAttribute("http://yet.another.uri", "doe", "john:doe", + "boolean", "false"); + + assertEquals("http://yet.another.uri", multi.getURI(6)); + assertEquals("doe", multi.getLocalName(6)); + assertEquals("john:doe", multi.getQName(6)); + assertEquals("boolean", multi.getType(6)); + assertEquals("false", multi.getValue(6)); + + // null case + multi.addAttribute(null, null, null, null, null); + assertEquals(null, multi.getURI(7)); + assertEquals(null, multi.getLocalName(7)); + assertEquals(null, multi.getQName(7)); + assertEquals(null, multi.getType(7)); + assertEquals(null, multi.getValue(7)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setAttribute", + args = { int.class, String.class, String.class, String.class, + String.class, String.class } + ) + public void testSetAttribute() { + // Ordinary case + multi.setAttribute(0, "http://yet.another.uri", "doe", "john:doe", + "boolean", "false"); + assertEquals("http://yet.another.uri", multi.getURI(0)); + assertEquals("doe", multi.getLocalName(0)); + assertEquals("john:doe", multi.getQName(0)); + assertEquals("boolean", multi.getType(0)); + assertEquals("false", multi.getValue(0)); + + // null case + multi.setAttribute(1, null, null, null, null, null); + assertEquals(null, multi.getURI(1)); + assertEquals(null, multi.getLocalName(1)); + assertEquals(null, multi.getQName(1)); + assertEquals(null, multi.getType(1)); + assertEquals(null, multi.getValue(1)); + + // Out of range + try { + multi.setAttribute(-1, "http://yet.another.uri", "doe", "john:doe", + "boolean", "false"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.setAttribute(5, "http://yet.another.uri", "doe", "john:doe", + "boolean", "false"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "removeAttribute", + args = { int.class } + ) + public void testRemoveAttribute() { + // Ordinary case + multi.removeAttribute(0); + assertEquals("http://some.uri", multi.getURI(0)); + assertEquals("bar", multi.getLocalName(0)); + assertEquals("ns1:bar", multi.getQName(0)); + assertEquals("string", multi.getType(0)); + assertEquals("xyz", multi.getValue(0)); + + // Out of range + try { + multi.removeAttribute(-1); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.removeAttribute(4); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setURI", + args = { int.class, String.class } + ) + public void testSetURI() { + // Ordinary case + multi.setURI(0, "http://yet.another.uri"); + assertEquals("http://yet.another.uri", multi.getURI(0)); + + // null case + multi.setURI(1, null); + assertEquals(null, multi.getURI(1)); + + // Out of range + try { + multi.setURI(-1, "http://yet.another.uri"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.setURI(5, "http://yet.another.uri"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setLocalName", + args = { int.class, String.class } + ) + public void testSetLocalName() { + // Ordinary case + multi.setLocalName(0, "john"); + assertEquals("john", multi.getLocalName(0)); + + // null case + multi.setLocalName(1, null); + assertEquals(null, multi.getLocalName(1)); + + // Out of range + try { + multi.setLocalName(-1, "john"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.setLocalName(5, "john"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setQName", + args = { int.class, String.class } + ) + public void testSetQName() { + // Ordinary case + multi.setQName(0, "john:doe"); + assertEquals("john:doe", multi.getQName(0)); + + // null case + multi.setQName(1, null); + assertEquals(null, multi.getQName(1)); + + // Out of range + try { + multi.setQName(-1, "john:doe"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.setQName(5, "john:doe"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setType", + args = { int.class, String.class } + ) + public void testSetType() { + // Ordinary case + multi.setType(0, "float"); + assertEquals("float", multi.getType(0)); + + // null case + multi.setType(1, null); + assertEquals(null, multi.getType(1)); + + // Out of range + try { + multi.setType(-1, "float"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.setType(5, "float"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setValue", + args = { int.class, String.class } + ) + public void testSetValue() { + // Ordinary case + multi.setValue(0, "too much"); + assertEquals("too much", multi.getValue(0)); + + // null case + multi.setValue(1, null); + assertEquals(null, multi.getValue(1)); + + // Out of range + try { + multi.setValue(-1, "too much"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + + try { + multi.setValue(5, "too much"); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected + } + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/DefaultHandlerTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/DefaultHandlerTest.java new file mode 100644 index 0000000..527048f --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/DefaultHandlerTest.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +import junit.framework.TestCase; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.helpers.LocatorImpl; + +import java.io.IOException; + +@TestTargetClass(DefaultHandler.class) +public class DefaultHandlerTest extends TestCase { + + /* + * Note: most of the tests have to check for an empty implementation of the + * respective methods and, as a result, are somewhat trivial. + */ + + private DefaultHandler h = new DefaultHandler(); + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "resolveEntity", + args = { String.class, String.class } + ) + public void testResolveEntity() { + try { + h.resolveEntity("publicID", "systemID"); + } catch (SAXException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "notationDecl", + args = { String.class, String.class, String.class } + ) + public void testNotationDecl() { + try { + h.notationDecl("name", "publicID", "systemID"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "unparsedEntityDecl", + args = { String.class, String.class, String.class, String.class } + ) + public void testUnparsedEntityDecl() { + try { + h.unparsedEntityDecl("name", "publicID", "systemID", + "notationName"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDocumentLocator", + args = { org.xml.sax.Locator.class } + ) + public void testSetDocumentLocator() { + h.setDocumentLocator(new LocatorImpl()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startDocument", + args = { } + ) + public void testStartDocument() { + try { + h.startDocument(); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endDocument", + args = { } + ) + public void testEndDocument() { + try { + h.endDocument(); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startPrefixMapping", + args = { String.class, String.class } + ) + public void testStartPrefixMapping() { + try { + h.startPrefixMapping("prefix", "uri"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endPrefixMapping", + args = { String.class } + ) + public void testEndPrefixMapping() { + try { + h.endPrefixMapping("prefix"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startElement", + args = { String.class, String.class, String.class, + Attributes.class } + ) + public void testStartElement() { + try { + h.startElement("uri", "name", "qname", new AttributesImpl()); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endElement", + args = { String.class, String.class, String.class } + ) + public void testEndElement() { + try { + h.endElement("uri", "name", "qname"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "characters", + args = { char[].class, int.class, int.class } + ) + public void testCharacters() { + try { + h.characters("The quick brown fox".toCharArray(), 4, 11); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "ignorableWhitespace", + args = { char[].class, int.class, int.class } + ) + public void testIgnorableWhitespace() { + try { + h.ignorableWhitespace(" ".toCharArray(), 4, 11); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "processingInstruction", + args = { String.class, String.class } + ) + public void testProcessingInstruction() { + try { + h.processingInstruction("target", "data"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "skippedEntity", + args = { String.class } + ) + public void testSkippedEntity() { + try { + h.skippedEntity("name"); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "warning", + args = { org.xml.sax.SAXParseException.class } + ) + public void testWarning() { + try { + h.warning(new SAXParseException("Foo", new LocatorImpl())); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "error", + args = { org.xml.sax.SAXParseException.class } + ) + public void testError() { + try { + h.error(new SAXParseException("Foo", new LocatorImpl())); + } catch (SAXException e) { + throw new RuntimeException(e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "fatalError", + args = { org.xml.sax.SAXParseException.class } + ) + public void testFatalError() { + // Ordinary case + try { + h.fatalError(new SAXParseException("Foo", new LocatorImpl())); + fail("SAXException expected"); + } catch (SAXException e) { + // Expected + } + + // No exception + try { + h.fatalError(null); + fail("NullPointerException expected"); + } catch (SAXException e) { + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/LocatorImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/LocatorImplTest.java new file mode 100644 index 0000000..e6b243c --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/LocatorImplTest.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import junit.framework.TestCase; + +import org.xml.sax.Locator; +import org.xml.sax.helpers.LocatorImpl; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@TestTargetClass(LocatorImpl.class) +public class LocatorImplTest extends TestCase { + + public static final String SYS = "mySystemID"; + + public static final String PUB = "myPublicID"; + + public static final int ROW = 1; + + public static final int COL = 2; + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "LocatorImpl", + args = { } + ) + public void testLocatorImpl() { + LocatorImpl l = new LocatorImpl(); + + assertEquals(null, l.getPublicId()); + assertEquals(null, l.getSystemId()); + assertEquals(0, l.getLineNumber()); + assertEquals(0, l.getColumnNumber()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "LocatorImpl", + args = { Locator.class } + ) + public void testLocatorImplLocator() { + LocatorImpl inner = new LocatorImpl(); + + inner.setPublicId(PUB); + inner.setSystemId(SYS); + inner.setLineNumber(ROW); + inner.setColumnNumber(COL); + + // Ordinary case + LocatorImpl outer = new LocatorImpl(inner); + + assertEquals(PUB, outer.getPublicId()); + assertEquals(SYS, outer.getSystemId()); + assertEquals(ROW, outer.getLineNumber()); + assertEquals(COL, outer.getColumnNumber()); + + // No locator + try { + outer = new LocatorImpl(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setPublicId", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getPublicId", + args = { } + ) + }) + public void testSetPublicIdGetPublicId() { + LocatorImpl l = new LocatorImpl(); + + l.setPublicId(PUB); + assertEquals(PUB, l.getPublicId()); + + l.setPublicId(null); + assertEquals(null, l.getPublicId()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setSystemId", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getSystemId", + args = { } + ) + }) + public void testSetSystemIdGetSystemId() { + LocatorImpl l = new LocatorImpl(); + + l.setSystemId(SYS); + assertEquals(SYS, l.getSystemId()); + + l.setSystemId(null); + assertEquals(null, l.getSystemId()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setLineNumber", + args = { int.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getLineNumber", + args = { } + ) + }) + public void testSetLineNumberGetLineNumber() { + LocatorImpl l = new LocatorImpl(); + + l.setLineNumber(ROW); + assertEquals(ROW, l.getLineNumber()); + + l.setLineNumber(0); + assertEquals(0, l.getLineNumber()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setColumnNumber", + args = { int.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getColumnNumber", + args = { } + ) + }) + public void testSetColumnNumberGetColumnNumber() { + LocatorImpl l = new LocatorImpl(); + + l.setColumnNumber(COL); + assertEquals(COL, l.getColumnNumber()); + + l.setColumnNumber(0); + assertEquals(0, l.getColumnNumber()); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/NamespaceSupportTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/NamespaceSupportTest.java new file mode 100644 index 0000000..b163b54 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/NamespaceSupportTest.java @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EmptyStackException; +import java.util.Enumeration; + +import junit.framework.TestCase; + +import org.xml.sax.helpers.NamespaceSupport; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@TestTargetClass( + value = NamespaceSupport.class, + untestedMethods = { + } +) +public class NamespaceSupportTest extends TestCase { + + final static String defaultUri = "http://www.android.com"; + final static String marketUri = "http://www.android.com/market"; + + NamespaceSupport ns; + ArrayList<String> expected; + + @Override + public void setUp() { + expected = new ArrayList<String>(); + expected.add("ak"); + expected.add("bk"); + + ns = new NamespaceSupport(); + ns.pushContext(); + + ns.declarePrefix("ak", marketUri); + ns.declarePrefix("bk", marketUri); + ns.declarePrefix("", defaultUri); + } + + @SuppressWarnings("unchecked") + @TestTargets ({ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "Checks that a new NamespaceSupport object contains a " + + "default context with two predefined prefixes.", + method = "NamespaceSupport", + args = {} + ), + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "popContext", + args = {} + ) + }) + public void testConstructor() { + String prefix; + boolean xmlPrefixExists = false; + + ns = new NamespaceSupport(); + Enumeration<String> prefixes = ns.getDeclaredPrefixes(); + + while (prefixes.hasMoreElements()) { + prefix = prefixes.nextElement(); + if (prefix.equals("xml")) xmlPrefixExists = true; + } + + assertTrue("Test 1: xml prefix does not exist.", xmlPrefixExists); + + // Check that only one context has been created by the constructor. + try { + ns.popContext(); + fail("Test 2: EmptyStackException expected."); + } catch (EmptyStackException e) { + // Expected. + } + } + + @TestTargets ({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "pushContext", + args = {} + ), + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "popContext", + args = {} + ) + }) + public void testPush_PopContext() { + int count; + + ns = new NamespaceSupport(); + count = countPrefixes(); + + ns.pushContext(); + ns.declarePrefix("dc", "http://www.purl.org/dc#"); + assertEquals("Test 1: Incorrect prefix count;", + count + 1, countPrefixes()); + + ns.popContext(); + assertEquals("Test 2: Incorrect prefix count;", + count, countPrefixes()); + + // Check that only one context has been created by pushContext(). + try { + ns.popContext(); + fail("Test 3: EmptyStackException expected."); + } catch (EmptyStackException e) { + // Expected. + } + } + + @TestTargets ({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "reset", + args = {} + ), + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "popContext", + args = {} + ) + }) + public void testReset() { + int count; + + ns = new NamespaceSupport(); + count = countPrefixes(); + + ns.pushContext(); + ns.declarePrefix("dc", "http://www.purl.org/dc#"); + + assertEquals("Test 1: Incorrect prefix count;", + count + 1, countPrefixes()); + + ns.reset(); + assertEquals("Test 2: Incorrect prefix count;", + count, countPrefixes()); + + // Check that only one context has been created by reset(). + try { + ns.popContext(); + fail("Test 3: EmptyStackException expected."); + } catch (EmptyStackException e) { + // Expected. + } + } + + @TestTargets ({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "declarePrefix", + args = {String.class, String.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getPrefix", + args = {String.class} + ) + }) + public void testDeclare_GetPrefix() { + ns.pushContext(); + + // Part 1: Check that xml and xmlns are not accepted as prefixes. + assertFalse("Test 1: Invalid prefix accepted.", + ns.declarePrefix("xml", marketUri)); + + assertFalse("Test 2: Invalid prefix accepted.", + ns.declarePrefix("xmlns", marketUri)); + + // Part 2: Check that declarePrefix and getPrefix work for valid + // prefixes. + assertTrue("Test 3: Valid prefix not accepted.", + ns.declarePrefix("ak", marketUri)); + + assertTrue("Test 4: Incorrect prefix returned.", + ns.getPrefix(marketUri).equals("ak")); + + assertTrue("Test 5: Valid prefix not accepted.", + ns.declarePrefix("bk", marketUri)); + + assertTrue("Test 6: Incorrect prefix returned.", + expected.contains(ns.getPrefix(marketUri))); + + assertTrue("Test 7: Valid prefix not accepted.", + ns.declarePrefix("", defaultUri)); + + // Part 3: Negative Tests for getPrefix. + assertNull("Test 8: Non-null value returned for the URI that is " + + "assigned to the default namespace.", + ns.getPrefix(defaultUri)); + + assertNull("Test 9: Non-null value returned for an unassigned URI.", + ns.getPrefix(defaultUri + "/42")); + } + + @SuppressWarnings("unchecked") + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getPrefixes", + args = {String.class} + ) + public void testGetPrefixesLjava_lang_String() { + ArrayList<String> prefixes; + + prefixes = Collections.list(ns.getPrefixes(marketUri)); + assertTrue("Test 1: Incorrect set of prefixes returned.", + expected.containsAll(prefixes) && prefixes.containsAll(expected)); + + prefixes = Collections.list(ns.getPrefixes(defaultUri)); + assertTrue("Test 2: Default namespace prefix should not be returned.", + prefixes.size() == 0); + + prefixes = Collections.list(ns.getPrefixes(NamespaceSupport.XMLNS)); + assertTrue("Test 3: xml prefix is missing.", + prefixes.contains("xml") && prefixes.size() == 1); + + prefixes = Collections.list(ns.getPrefixes(defaultUri + "/42")); + assertTrue("Test 4: Non-empty enumeration returned for an unassigned URI.", + prefixes.size() == 0); + } + + @SuppressWarnings("unchecked") + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getPrefixes", + args = {} + ) + public void testGetPrefixes() { + ArrayList<String> prefixes; + + expected.add("xml"); + + prefixes = Collections.list(ns.getPrefixes()); + assertTrue("Test 1: Incorrect set of prefixes returned.", + expected.containsAll(prefixes) && prefixes.containsAll(expected)); + } + + @SuppressWarnings("unchecked") + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getDeclaredPrefixes", + args = {} + ) + public void testGetDeclaredPrefixes() { + ArrayList<String> prefixes; + + expected.add(""); + + prefixes = Collections.list(ns.getDeclaredPrefixes()); + assertTrue("Test 1: Incorrect set of prefixes returned.", + expected.containsAll(prefixes) && prefixes.containsAll(expected)); + } + + @TestTargets ({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getURI", + args = {String.class} + ), + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "popContext", + args = {} + ) + }) + public void testGetUri() { + assertEquals("Test 1: Incorrect URI returned;", + marketUri, ns.getURI("bk")); + assertEquals("Test 2: Incorrect URI returned;", + defaultUri, ns.getURI("")); + assertNull("Test 3: Null expected for not-existing prefix.", + ns.getURI("ck")); + + ns.popContext(); + assertNull("Test 4: Null expected for not-existing prefix.", + ns.getURI("bk")); + assertEquals("Test 5: Incorrect URI returned;", + NamespaceSupport.XMLNS, ns.getURI("xml")); + } + + @TestTargets ({ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "setNamespaceDeclUris", + args = {boolean.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "isNamespaceDeclUris", + args = {} + ) + }) + public void testNamespaceDeclUris() { + + assertFalse("Test 1: Incorrect default value returned by isNamespaceDeclUris().", + ns.isNamespaceDeclUris()); + + try { + ns.setNamespaceDeclUris(true); + fail("Test 2: IllegalStateException expected since a context has already been pushed in setUp()."); + } catch (IllegalStateException e) { + // Expected. + } + + ns = new NamespaceSupport(); + ns.setNamespaceDeclUris(true); + assertTrue("Test 3: Incorrect value returned by isNamespaceDeclUris().", + ns.isNamespaceDeclUris()); + + ns.setNamespaceDeclUris(false); + assertFalse("Test 4: Incorrect value returned by isNamespaceDeclUris().", + ns.isNamespaceDeclUris()); + } + + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "processName", + args = {String.class, String[].class, boolean.class} + ) + public void testProcessName_Element() { + String[] parts = new String[3]; + + assertNotNull("Test 1: Non-null value expected.", + ns.processName("ak:hello", parts, false)); + assertEquals("Test 2: Incorrect namespace URI;", marketUri, parts[0]); + assertEquals("Test 3: Incorrect local name;", "hello", parts[1]); + assertEquals("Test 4: Incorrect raw name;", "ak:hello", parts[2]); + + assertNotNull("Test 5: Non-null value expected.", + ns.processName("bk:", parts, false)); + assertEquals("Test 6: Incorrect namespace URI;", marketUri, parts[0]); + assertEquals("Test 7: Incorrect local name;", "", parts[1]); + assertEquals("Test 8: Incorrect raw name;", "bk:", parts[2]); + + assertNotNull("Test 9: Non-null value expected.", + ns.processName("world", parts, false)); + assertEquals("Test 10: Incorrect namespace URI;", defaultUri, parts[0]); + assertEquals("Test 11: Incorrect local name;", "world", parts[1]); + assertEquals("Test 12: Incorrect raw name;", "world", parts[2]); + + assertNull("Test 13: Null expected for undeclared prefix.", + ns.processName("ck:lorem", parts, false)); + + assertNull("Test 14: Null expected for xmlns prefix.", + ns.processName("xmlns:ipsum", parts, false)); + + ns = new NamespaceSupport(); + ns.pushContext(); + assertNotNull("Test 15: Non-null value expected.", + ns.processName("world", parts, false)); + assertEquals("Test 16: Incorrect namespace URI;", "", parts[0]); + assertEquals("Test 17: Incorrect local name;", "world", parts[1]); + assertEquals("Test 18: Incorrect raw name;", "world", parts[2]); + } + + @TestTargets ({ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "setNamespaceDeclUris", + args = {boolean.class} + ), + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "processName", + args = {String.class, String[].class, boolean.class} + ) + }) + public void testProcessName_Attribute() { + String[] parts = new String[3]; + + assertNotNull("Test 1: Non-null value expected.", + ns.processName("ak:hello", parts, true)); + assertEquals("Test 2: Incorrect namespace URI;", marketUri, parts[0]); + assertEquals("Test 3: Incorrect local name;", "hello", parts[1]); + assertEquals("Test 4: Incorrect raw name;", "ak:hello", parts[2]); + + assertNotNull("Test 5: Non-null value expected.", + ns.processName("bk:", parts, true)); + assertEquals("Test 6: Incorrect namespace URI;", marketUri, parts[0]); + assertEquals("Test 7: Incorrect local name;", "", parts[1]); + assertEquals("Test 8: Incorrect raw name;", "bk:", parts[2]); + + assertNotNull("Test 9: Non-null value expected.", + ns.processName("world", parts, true)); + assertEquals("Test 10: Incorrect namespace URI;", "", parts[0]); + assertEquals("Test 11: Incorrect local name;", "world", parts[1]); + assertEquals("Test 12: Incorrect raw name;", "world", parts[2]); + + assertNull("Test 13: Null expected for undeclared prefix.", + ns.processName("ck:lorem", parts, true)); + + assertNull("Test 14: Null expected for xmlns prefix.", + ns.processName("xmlns:ipsum", parts, true)); + + ns = new NamespaceSupport(); + ns.setNamespaceDeclUris(true); + ns.pushContext(); + assertNotNull("Test 15: Non-null value expected.", + ns.processName("xmlns", parts, true)); + assertEquals("Test 16: Incorrect namespace URI;", NamespaceSupport.NSDECL, parts[0]); + assertEquals("Test 17: Incorrect local name;", "xmlns", parts[1]); + assertEquals("Test 18: Incorrect raw name;", "xmlns", parts[2]); + } + + @SuppressWarnings("unchecked") + private int countPrefixes() + { + ArrayList<String> prefixes = Collections.list(ns.getPrefixes()); + return prefixes.size(); + } +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java new file mode 100644 index 0000000..27a7e78 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.xml.sax.AttributeList; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.Parser; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.helpers.AttributeListImpl; +import org.xml.sax.helpers.LocatorImpl; +import org.xml.sax.helpers.ParserAdapter; + +import tests.api.org.xml.sax.support.MethodLogger; +import tests.api.org.xml.sax.support.MockHandler; +import tests.api.org.xml.sax.support.MockParser; +import tests.api.org.xml.sax.support.MockResolver; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@SuppressWarnings("deprecation") +@TestTargetClass(ParserAdapter.class) +public class ParserAdapterTest extends TestCase { + + // Note: In many cases we can only test that delegation works + // properly. The rest is outside the scope of the specification. + + private final static String FEATURES = "http://xml.org/sax/features/"; + + private final static String NAMESPACES = FEATURES + "namespaces"; + + private final static String NAMESPACE_PREFIXES = FEATURES + + "namespace-prefixes"; + + private final static String XMLNS_URIs = FEATURES + "xmlns-uris"; + + private MethodLogger logger = new MethodLogger(); + + private MockHandler handler = new MockHandler(logger); + + private Parser parser = new MockParser(logger); + + private ParserAdapter adapter = new ParserAdapter(parser); + + private void assertEquals(Object[] a, Object[] b) { + assertEquals(a.length, b.length); + + for (int i = 0; i < a.length; i++) { + assertEquals("Element #" + i + " must be equal", a[i], b[i]); + } + } + + @Override + public void setUp() { + adapter.setContentHandler(handler); + adapter.setDTDHandler(handler); + adapter.setErrorHandler(handler); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "ParserAdapter", + args = { } + ) + public void testParserAdapter() { + System.setProperty("org.xml.sax.parser", + "tests.api.org.xml.sax.support.DoNothingParser"); + + try { + new ParserAdapter(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "ParserAdapter", + args = { Parser.class } + ) + public void testParserAdapterParser() { + // Ordinary case + @SuppressWarnings("unused") + ParserAdapter adapter = new ParserAdapter(parser); + + // Null case + try { + adapter = new ParserAdapter(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getFeature", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setFeature", + args = { String.class, boolean.class } + ) + }) + public void testGetSetFeature() { + String[] features = new String[] { NAMESPACES, NAMESPACE_PREFIXES, + XMLNS_URIs }; + + for (String s: features) { + try { + adapter.setFeature(s, true); + assertEquals(true, adapter.getFeature(s)); + + adapter.setFeature(s, false); + assertEquals(false, adapter.getFeature(s)); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + try { + adapter.setFeature("http://argle.bargle", true); + fail("SAXNotRecognizedException expected"); + } catch (SAXNotRecognizedException e) { + // Expected + } catch (SAXNotSupportedException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getProperty", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setProperty", + args = { String.class, Object.class } + ) + }) + public void testGetSetProperty() { + try { + adapter.setProperty("http://argle.bargle", ":)"); + fail("SAXNotRecognizedException expected"); + } catch (SAXNotRecognizedException e) { + // Expected + } catch (SAXNotSupportedException e) { + throw new RuntimeException("Unexpected exception", e); + } + + try { + adapter.getProperty("http://argle.bargle"); + fail("SAXNotRecognizedException expected"); + } catch (SAXNotRecognizedException e) { + // Expected + } catch (SAXNotSupportedException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getEntityResolver", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setEntityResolver", + args = { EntityResolver.class } + ) + }) + public void testGetSetEntityResolver() { + EntityResolver resolver = new MockResolver(); + + adapter.setEntityResolver(resolver); + assertEquals(resolver, adapter.getEntityResolver()); + + adapter.setEntityResolver(null); + assertEquals(null, adapter.getEntityResolver()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getDTDHandler", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDTDHandler", + args = { DTDHandler.class } + ) + }) + public void testGetSetDTDHandler() { + adapter.setDTDHandler(null); + assertEquals(null, adapter.getDTDHandler()); + + adapter.setDTDHandler(handler); + assertEquals(handler, adapter.getDTDHandler()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getContentHandler", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setContentHandler", + args = { ContentHandler.class } + ) + }) + public void testGetSetContentHandler() { + adapter.setContentHandler(null); + assertEquals(null, adapter.getContentHandler()); + + adapter.setContentHandler(handler); + assertEquals(handler, adapter.getContentHandler()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getErrorHandler", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setErrorHandler", + args = { ErrorHandler.class } + ) + }) + public void testGetSetErrorHandler() { + adapter.setErrorHandler(null); + assertEquals(null, adapter.getErrorHandler()); + + adapter.setErrorHandler(handler); + assertEquals(handler, adapter.getErrorHandler()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "parse", + args = { String.class } + ) + public void testParseString() { + try { + adapter.parse("foo"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + + // The SAX RI creates an InputSource itself and then delegates to the + // "other" parse method. + assertEquals("parse", logger.getMethod()); + assertEquals(InputSource.class, logger.getArgs()[0].getClass()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "parse", + args = { InputSource.class } + ) + public void testParseInputSource() { + InputSource source = new InputSource("foo"); + + try { + adapter.parse(source); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals("parse", logger.getMethod()); + assertEquals(new Object[] { source }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDocumentLocator", + args = { Locator.class } + ) + public void testSetDocumentLocator() { + Locator l = new LocatorImpl(); + + adapter.setDocumentLocator(l); + + assertEquals(logger.size(), 1); + assertEquals("setDocumentLocator", logger.getMethod()); + assertEquals(new Object[] { l }, logger.getArgs()); + + adapter.setDocumentLocator(null); + + assertEquals(logger.size(), 2); + assertEquals("setDocumentLocator", logger.getMethod()); + assertEquals(new Object[] { null }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startDocument", + args = { } + ) + public void testStartDocument() { + try { + adapter.startDocument(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("startDocument", logger.getMethod()); + assertEquals(new Object[] {}, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endDocument", + args = { } + ) + public void testEndDocument() { + try { + adapter.endDocument(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("endDocument", logger.getMethod()); + assertEquals(new Object[] {}, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startElement", + args = { String.class, AttributeList.class } + ) + public void testStartElement() { + AttributeListImpl atts = new AttributeListImpl(); + atts.addAttribute("john:doe", "int", "42"); + + try { + adapter.startDocument(); + adapter.startElement("foo:bar", atts); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals("startElement", logger.getMethod()); + assertEquals("", logger.getArgs()[0]); + assertEquals("", logger.getArgs()[1]); + assertEquals("foo:bar", logger.getArgs()[2]); + assertEquals("john:doe", ((Attributes)logger.getArgs()[3]).getQName(0)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endElement", + args = { String.class } + ) + public void testEndElement() { + AttributeListImpl atts = new AttributeListImpl(); + atts.addAttribute("john:doe", "int", "42"); + + try { + adapter.startDocument(); + adapter.startElement("foo:bar", atts); + adapter.endElement("foo:bar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals("endElement", logger.getMethod()); + assertEquals(new String[] { "", "", "foo:bar" }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "characters", + args = { char[].class, int.class, int.class } + ) + public void testCharacters() { + char[] ch = "Android".toCharArray(); + + try { + adapter.characters(ch, 2, 5); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("characters", logger.getMethod()); + assertEquals(new Object[] { ch, 2, 5 }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "ignorableWhitespace", + args = { char[].class, int.class, int.class } + ) + public void testIgnorableWhitespace() { + char[] ch = " ".toCharArray(); + + try { + adapter.ignorableWhitespace(ch, 0, 5); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("ignorableWhitespace", logger.getMethod()); + assertEquals(new Object[] { ch, 0, 5 }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "processingInstruction", + args = { String.class, String.class } + ) + public void testProcessingInstruction() { + try { + adapter.processingInstruction("foo", "bar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("processingInstruction", logger.getMethod()); + assertEquals(new Object[] { "foo" , "bar" }, logger.getArgs()); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java new file mode 100644 index 0000000..ebf2a04 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +import junit.framework.TestCase; + +import org.xml.sax.helpers.ParserFactory; + +@SuppressWarnings("deprecation") +@TestTargetClass(ParserFactory.class) +public class ParserFactoryTest extends TestCase { + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "makeParser", + args = { }, + notes = "Checks everything except META-INF case" + ) + public void testMakeParser() { + // Property not set at all + try { + ParserFactory.makeParser(); + } catch (NullPointerException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Unknown class + System.setProperty("org.xml.sax.parser", "foo.bar.SAXParser"); + + try { + ParserFactory.makeParser(); + } catch (ClassNotFoundException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Non-accessible class + System.setProperty("org.xml.sax.parser", + "tests.api.org.xml.sax.support.NoAccessParser"); + + try { + ParserFactory.makeParser(); + } catch (IllegalAccessException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Non-instantiable class + System.setProperty("org.xml.sax.parser", + "tests.api.org.xml.sax.support.NoInstanceParser"); + + try { + ParserFactory.makeParser(); + } catch (InstantiationException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Non-Parser class + System.setProperty("org.xml.sax.parser", + "tests.api.org.xml.sax.support.NoSubclassParser"); + + try { + ParserFactory.makeParser(); + } catch (ClassCastException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Good one, finally + System.setProperty("org.xml.sax.parser", + "tests.api.org.xml.sax.support.DoNothingParser"); + + try { + ParserFactory.makeParser(); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "makeParser", + args = { String.class } + ) + public void testMakeParserString() { + // No class + try { + ParserFactory.makeParser(null); + } catch (NullPointerException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Unknown class + try { + ParserFactory.makeParser("foo.bar.SAXParser"); + } catch (ClassNotFoundException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Non-accessible class + try { + ParserFactory.makeParser( + "tests.api.org.xml.sax.support.NoAccessParser"); + } catch (IllegalAccessException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Non-instantiable class + try { + ParserFactory.makeParser( + "tests.api.org.xml.sax.support.NoInstanceParser"); + } catch (InstantiationException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Non-Parser class + try { + ParserFactory.makeParser( + "tests.api.org.xml.sax.support.NoSubclassParser"); + } catch (ClassCastException e) { + // Expected + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Good one, finally + try { + ParserFactory.makeParser( + "tests.api.org.xml.sax.support.DoNothingParser"); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLFilterImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLFilterImplTest.java new file mode 100644 index 0000000..6586461 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLFilterImplTest.java @@ -0,0 +1,678 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.LocatorImpl; +import org.xml.sax.helpers.XMLFilterImpl; + +import tests.api.org.xml.sax.support.MethodLogger; +import tests.api.org.xml.sax.support.MockFilter; +import tests.api.org.xml.sax.support.MockHandler; +import tests.api.org.xml.sax.support.MockResolver; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@TestTargetClass(XMLFilterImpl.class) +public class XMLFilterImplTest extends TestCase { + + // Note: In many cases we can only test that delegation works + // properly. The rest is outside the scope of the specification. + + private MethodLogger logger = new MethodLogger(); + + private MockHandler handler = new MockHandler(logger); + + private XMLFilterImpl parent = new MockFilter(logger); + + private XMLFilterImpl child = new XMLFilterImpl(parent); + + private XMLFilterImpl orphan = new XMLFilterImpl(); + + private void assertEquals(Object[] a, Object[] b) { + assertEquals(a.length, b.length); + + for (int i = 0; i < a.length; i++) { + assertEquals("Element #" + i + " must be equal", a[i], b[i]); + } + } + + public void setUp() { + parent.setContentHandler(handler); + parent.setDTDHandler(handler); + parent.setErrorHandler(handler); + + child.setContentHandler(handler); + child.setDTDHandler(handler); + child.setErrorHandler(handler); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "XMLFilterImpl", + args = { } + ) + public void testXMLFilterImpl() { + assertEquals(null, parent.getParent()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "XMLFilterImpl", + args = { XMLReader.class } + ) + public void testXMLFilterImplXMLReader() { + // Ordinary case + assertEquals(null, parent.getParent()); + + // null case + XMLFilterImpl filter = new XMLFilterImpl(null); + assertEquals(null, filter.getParent()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getParent", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setParent", + args = { XMLReader.class } + ) + }) + public void testGetSetParent() { + child.setParent(null); + assertEquals(null, child.getParent()); + + child.setParent(parent); + assertEquals(parent, child.getParent()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getFeature", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setFeature", + args = { String.class, boolean.class } + ) + }) + public void testGetSetFeature() { + // Ordinary case + try { + child.setFeature("foo", true); + assertEquals(true, child.getFeature("foo")); + + child.setFeature("foo", false); + assertEquals(false, child.getFeature("foo")); + } catch (SAXNotRecognizedException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (SAXNotSupportedException e) { + throw new RuntimeException("Unexpected exception", e); + } + + // No parent case + try { + orphan.setFeature("foo", false); + fail("SAXNotRecognizedException expected"); + } catch (SAXNotRecognizedException e) { + // Expected + } catch (SAXNotSupportedException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getProperty", + args = { String.class } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setProperty", + args = { String.class, Object.class } + ) + }) + public void testGetSetProperty() { + // Ordinary case + try { + child.setProperty("foo", "bar"); + assertEquals("bar", child.getProperty("foo")); + + child.setProperty("foo", null); + assertEquals(null, child.getProperty("foo")); + } catch (SAXNotRecognizedException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (SAXNotSupportedException e) { + throw new RuntimeException("Unexpected exception", e); + } + + // No parent case + try { + orphan.setProperty("foo", "bar"); + fail("SAXNotRecognizedException expected"); + } catch (SAXNotRecognizedException e) { + // Expected + } catch (SAXNotSupportedException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getEntityResolver", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setEntityResolver", + args = { EntityResolver.class } + ) + }) + public void testGetSetEntityResolver() { + EntityResolver resolver = new MockResolver(); + + parent.setEntityResolver(resolver); + assertEquals(resolver, parent.getEntityResolver()); + + parent.setEntityResolver(null); + assertEquals(null, parent.getEntityResolver()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getDTDHandler", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDTDHandler", + args = { DTDHandler.class } + ) + }) + public void testGetSetDTDHandler() { + parent.setDTDHandler(null); + assertEquals(null, parent.getDTDHandler()); + + parent.setDTDHandler(handler); + assertEquals(handler, parent.getDTDHandler()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getContentHandler", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setContentHandler", + args = { ContentHandler.class } + ) + }) + public void testGetSetContentHandler() { + parent.setContentHandler(null); + assertEquals(null, parent.getContentHandler()); + + parent.setContentHandler(handler); + assertEquals(handler, parent.getContentHandler()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getErrorHandler", + args = { } + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setErrorHandler", + args = { ErrorHandler.class } + ) + }) + public void testGetSetErrorHandler() { + parent.setErrorHandler(null); + assertEquals(null, parent.getErrorHandler()); + + parent.setErrorHandler(handler); + assertEquals(handler, parent.getErrorHandler()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "parse", + args = { InputSource.class } + ) + public void testParseInputSource() { + InputSource is = new InputSource(); + + // Ordinary case + try { + child.parse(is); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(1, logger.size()); + assertEquals("parse", logger.getMethod()); + + // No parent case + try { + orphan.parse(is); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "parse", + args = { String.class } + ) + public void testParseString() { + // Ordinary case + try { + child.parse("foo"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(1, logger.size()); + assertEquals("parse", logger.getMethod()); + + // No parent case + try { + orphan.parse("foo"); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "resolveEntity", + args = { String.class, String.class } + ) + public void testResolveEntity() { + InputSource expected = new InputSource(); + + MockResolver resolver = new MockResolver(); + resolver.addEntity("foo", "bar", expected); + + InputSource result = null; + + parent.setEntityResolver(resolver); + + // Ordinary case + try { + result = parent.resolveEntity("foo", "bar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(expected, result); + + // No entity resolver case + parent.setEntityResolver(null); + + try { + result = parent.resolveEntity("foo", "bar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(null, result); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "notationDecl", + args = { String.class, String.class, String.class } + ) + public void testNotationDecl() { + try { + parent.notationDecl("foo", "bar", "foobar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("notationDecl", logger.getMethod()); + assertEquals(new Object[] { "foo", "bar", "foobar" }, + logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "unparsedEntityDecl", + args = { String.class, String.class, String.class, String.class } + ) + public void testUnparsedEntityDecl() { + try { + parent.unparsedEntityDecl("foo", "bar", "gabba", "hey"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("unparsedEntityDecl", logger.getMethod()); + assertEquals(new Object[] { "foo", "bar", "gabba", "hey" }, + logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDocumentLocator", + args = { Locator.class } + ) + public void testSetDocumentLocator() { + Locator l = new LocatorImpl(); + + child.setDocumentLocator(l); + + assertEquals(logger.size(), 1); + assertEquals("setDocumentLocator", logger.getMethod()); + assertEquals(new Object[] { l }, logger.getArgs()); + + child.setDocumentLocator(null); + + assertEquals(logger.size(), 2); + assertEquals("setDocumentLocator", logger.getMethod()); + assertEquals(new Object[] { null }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startDocument", + args = { } + ) + public void testStartDocument() { + try { + parent.startDocument(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("startDocument", logger.getMethod()); + assertEquals(new Object[] {}, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endDocument", + args = { } + ) + public void testEndDocument() { + try { + parent.endDocument(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("endDocument", logger.getMethod()); + assertEquals(new Object[] {}, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startPrefixMapping", + args = { String.class, String.class } + ) + public void testStartPrefixMapping() { + try { + parent.startPrefixMapping("foo", "http://some.uri"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("startPrefixMapping", logger.getMethod()); + assertEquals(new Object[] { "foo", "http://some.uri" }, + logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endPrefixMapping", + args = { String.class } + ) + public void testEndPrefixMapping() { + try { + parent.endPrefixMapping("foo"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("endPrefixMapping", logger.getMethod()); + assertEquals(new Object[] { "foo" }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startElement", + args = { String.class, String.class, String.class, Attributes.class } + ) + public void testStartElement() { + Attributes atts = new AttributesImpl(); + + try { + parent.startElement("http://some.uri", "bar", "foo:bar", atts); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("startElement", logger.getMethod()); + assertEquals(new Object[] { "http://some.uri", "bar", "foo:bar", atts }, + logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endElement", + args = { String.class, String.class, String.class } + ) + public void testEndElement() { + try { + parent.endElement("http://some.uri", "bar", "foo:bar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("endElement", logger.getMethod()); + assertEquals(new Object[] { "http://some.uri", "bar", "foo:bar" }, + logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "characters", + args = { char[].class, int.class, int.class } + ) + public void testCharacters() { + char[] ch = "Android".toCharArray(); + + try { + parent.characters(ch, 2, 5); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("characters", logger.getMethod()); + assertEquals(new Object[] { ch, 2, 5 }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "ignorableWhitespace", + args = { char[].class, int.class, int.class } + ) + public void testIgnorableWhitespace() { + char[] ch = " ".toCharArray(); + + try { + parent.ignorableWhitespace(ch, 0, 5); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("ignorableWhitespace", logger.getMethod()); + assertEquals(new Object[] { ch, 0, 5 }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "processingInstruction", + args = { String.class, String.class } + ) + public void testProcessingInstruction() { + try { + parent.processingInstruction("foo", "bar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("processingInstruction", logger.getMethod()); + assertEquals(new Object[] { "foo", "bar" }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "skippedEntity", + args = { String.class } + ) + public void testSkippedEntity() { + try { + parent.skippedEntity("foo"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("skippedEntity", logger.getMethod()); + assertEquals(new Object[] { "foo" }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "warning", + args = { SAXParseException.class } + ) + public void testWarning() { + SAXParseException exception = new SAXParseException("Oops!", null); + + try { + parent.warning(exception); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("warning", logger.getMethod()); + assertEquals(new Object[] { exception }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "error", + args = { SAXParseException.class } + ) + public void testError() { + SAXParseException exception = new SAXParseException("Oops!", null); + + try { + parent.error(exception); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("error", logger.getMethod()); + assertEquals(new Object[] { exception }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "fatalError", + args = { SAXParseException.class } + ) + public void testFatalError() { + SAXParseException exception = new SAXParseException("Oops!", null); + + try { + parent.fatalError(exception); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("fatalError", logger.getMethod()); + assertEquals(new Object[] { exception }, logger.getArgs()); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java new file mode 100644 index 0000000..20488c5 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import java.io.IOException; +import java.util.Locale; + +import junit.framework.TestCase; + +import org.xml.sax.AttributeList; +import org.xml.sax.Attributes; +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.LocatorImpl; +import org.xml.sax.helpers.XMLReaderAdapter; + +import tests.api.org.xml.sax.support.MethodLogger; +import tests.api.org.xml.sax.support.MockHandler; +import tests.api.org.xml.sax.support.MockReader; +import tests.api.org.xml.sax.support.MockResolver; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +@SuppressWarnings("deprecation") +@TestTargetClass(XMLReaderAdapter.class) +public class XMLReaderAdapterTest extends TestCase { + + // Note: In many cases we can only test that delegation works + // properly. The rest is outside the scope of the specification. + + private MethodLogger logger = new MethodLogger(); + + private MockHandler handler = new MockHandler(logger); + + private XMLReader reader = new MockReader(logger); + + private XMLReaderAdapter adapter = new XMLReaderAdapter(reader); + + private void assertEquals(Object[] a, Object[] b) { + assertEquals(a.length, b.length); + + for (int i = 0; i < a.length; i++) { + assertEquals("Element #" + i + " must be equal", a[i], b[i]); + } + } + + @Override + public void setUp() { + adapter.setDocumentHandler(handler); + adapter.setDTDHandler(handler); + adapter.setErrorHandler(handler); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "XMLReaderAdapter", + args = { } + ) + public void testXMLReaderAdapter() { + System.setProperty("org.xml.sax.driver", + "tests.api.org.xml.sax.support.DoNothingXMLReader"); + + try { + new XMLReaderAdapter(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "XMLReaderAdapter", + args = { XMLReader.class } + ) + public void testXMLReaderAdapterXMLReader() { + // Ordinary case + @SuppressWarnings("unused") + XMLReaderAdapter adapter = new XMLReaderAdapter(reader); + + // Null case + try { + adapter = new XMLReaderAdapter(null); + fail("NullPointerException expected"); + } catch (NullPointerException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setLocale", + args = { Locale.class } + ) + public void testSetLocale() { + // SAX RI does not support this, hence always expect exception + try { + adapter.setLocale(Locale.getDefault()); + fail("SAXException expected"); + } catch (SAXException e) { + // Expected + } + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setEntityResolver", + args = { EntityResolver.class } + ) + public void testSetEntityResolver() { + EntityResolver resolver = new MockResolver(); + + // Ordinary case + adapter.setEntityResolver(resolver); + assertEquals(resolver, reader.getEntityResolver()); + + // null case + adapter.setEntityResolver(null); + assertEquals(null, reader.getEntityResolver()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDTDHandler", + args = { DTDHandler.class } + ) + public void testSetDTDHandler() { + // Ordinary case + assertEquals(handler, reader.getDTDHandler()); + + // null case + adapter.setDTDHandler(null); + assertEquals(null, reader.getDTDHandler()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDocumentHandler", + args = { DocumentHandler.class } + ) + public void testSetDocumentHandler() { + // There is no getter for the DocumentHandler, so we can only test + // indirectly whether is has been set correctly. + try { + adapter.startDocument(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals("startDocument", logger.getMethod()); + assertEquals(new Object[] { }, logger.getArgs()); + + // null case + adapter.setDocumentHandler(null); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setErrorHandler", + args = { ErrorHandler.class } + ) + public void testSetErrorHandler() { + // Ordinary case + assertEquals(handler, reader.getErrorHandler()); + + // null case + adapter.setErrorHandler(null); + assertEquals(null, reader.getErrorHandler()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "parse", + args = { String.class } + ) + public void testParseString() { + try { + adapter.parse("foo"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + + // The SAX RI creates an InputSource itself and then delegates to the + // "other" parse method. + assertEquals("parse", logger.getMethod(0)); + assertEquals(InputSource.class, logger.getArgs(0)[0].getClass()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "parse", + args = { InputSource.class } + ) + public void testParseInputSource() { + InputSource source = new InputSource("foo"); + + try { + adapter.parse(source); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals("parse", logger.getMethod()); + assertEquals(new Object[] { source }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "setDocumentLocator", + args = { Locator.class } + ) + public void testSetDocumentLocator() { + // Ordinary case + LocatorImpl locator = new LocatorImpl(); + adapter.setDocumentLocator(locator); + + assertEquals("setDocumentLocator", logger.getMethod()); + assertEquals(new Object[] { locator }, logger.getArgs()); + + // null case (for the DocumentHandler itself!) + adapter.setDocumentHandler(null); + adapter.setDocumentLocator(locator); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startDocument", + args = { } + ) + public void testStartDocument() { + try { + adapter.startDocument(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("startDocument", logger.getMethod()); + assertEquals(new Object[] {}, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endDocument", + args = { } + ) + public void testEndDocument() { + try { + adapter.endDocument(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("endDocument", logger.getMethod()); + assertEquals(new Object[] {}, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startPrefixMapping", + args = { String.class, String.class } + ) + public void testStartPrefixMapping() { + adapter.startPrefixMapping("foo", "http://some.uri"); + assertEquals(logger.size(), 0); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endPrefixMapping", + args = { String.class } + ) + public void testEndPrefixMapping() { + adapter.endPrefixMapping("foo"); + assertEquals(logger.size(), 0); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "startElement", + args = { String.class, String.class, String.class, Attributes.class } + ) + public void testStartElement() { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute("http://some.other.uri", "gabba", "gabba:hey", + "int", "42"); + + try { + adapter.startElement("http://some.uri", "bar", "foo:bar", atts); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("startElement", logger.getMethod()); + assertEquals("foo:bar", logger.getArgs()[0]); + assertEquals("gabba:hey", + ((AttributeList)logger.getArgs()[1]).getName(0)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "endElement", + args = { String.class, String.class, String.class } + ) + public void testEndElement() { + try { + adapter.endElement("http://some.uri", "bar", "foo:bar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("endElement", logger.getMethod()); + assertEquals(new Object[] { "foo:bar" }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "characters", + args = { char[].class, int.class, int.class } + ) + public void testCharacters() { + char[] ch = "Android".toCharArray(); + + try { + adapter.characters(ch, 2, 5); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("characters", logger.getMethod()); + assertEquals(new Object[] { ch, 2, 5 }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "ignorableWhitespace", + args = { char[].class, int.class, int.class } + ) + public void testIgnorableWhitespace() { + char[] ch = " ".toCharArray(); + + try { + adapter.ignorableWhitespace(ch, 0, 5); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("ignorableWhitespace", logger.getMethod()); + assertEquals(new Object[] { ch, 0, 5 }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "processingInstruction", + args = { String.class, String.class } + ) + public void testProcessingInstruction() { + try { + adapter.processingInstruction("foo", "bar"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 1); + assertEquals("processingInstruction", logger.getMethod()); + assertEquals(new Object[] { "foo" , "bar" }, logger.getArgs()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "skippedEntity", + args = { String.class } + ) + public void testSkippedEntity() { + try { + adapter.skippedEntity("foo"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + assertEquals(logger.size(), 0); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java new file mode 100644 index 0000000..bfb1bd1 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.helpers; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; + +import junit.framework.TestCase; + +import org.xml.sax.SAXException; +import org.xml.sax.helpers.XMLReaderFactory; + +@TestTargetClass(XMLReaderFactory.class) +public class XMLReaderFactoryTest extends TestCase { + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + method = "createXMLReader", + args = { }, + notes = "Checks everything except META-INF case" + ) + public void testCreateXMLReader() { + // Property not set at all + try { + XMLReaderFactory.createXMLReader(); + } catch (SAXException e) { + // Expected + } + + // Unknown class + System.setProperty("org.xml.sax.driver", "foo.bar.XMLReader"); + + try { + XMLReaderFactory.createXMLReader(); + } catch (SAXException e) { + // Expected + } + + // Non-accessible class + System.setProperty("org.xml.sax.driver", + "tests.api.org.xml.sax.support.NoAccessXMLReader"); + + try { + XMLReaderFactory.createXMLReader(); + } catch (SAXException e) { + // Expected + } + + // Non-instantiable class + System.setProperty("org.xml.sax.driver", + "tests.api.org.xml.sax.support.NoInstanceXMLReader"); + + try { + XMLReaderFactory.createXMLReader(); + } catch (SAXException e) { + // Expected + } + + // Non-XMLReader class + System.setProperty("org.xml.sax.driver", + "tests.api.org.xml.sax.support.NoSubclassXMLReader"); + + try { + XMLReaderFactory.createXMLReader(); + } catch (ClassCastException e) { + // Expected + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Good one, finally + System.setProperty("org.xml.sax.driver", + "tests.api.org.xml.sax.support.DoNothingXMLReader"); + + try { + XMLReaderFactory.createXMLReader(); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "createXMLReader", + args = { String.class } + ) + public void testMakeParserString() { + // No class + try { + XMLReaderFactory.createXMLReader(null); + } catch (NullPointerException e) { + // Expected + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + // Unknown class + try { + XMLReaderFactory.createXMLReader("foo.bar.XMLReader"); + } catch (SAXException e) { + // Expected + } + + // Non-accessible class + try { + XMLReaderFactory.createXMLReader( + "tests.api.org.xml.sax.support.NoAccessXMLReader"); + } catch (SAXException e) { + // Expected + } + + // Non-instantiable class + try { + XMLReaderFactory.createXMLReader( + "tests.api.org.xml.sax.support.NoInstanceXMLReader"); + } catch (SAXException e) { + // Expected + } + + // Non-Parser class + try { + XMLReaderFactory.createXMLReader( + "tests.api.org.xml.sax.support.NoSubclassXMLReader"); + } catch (SAXException e) { + // Expected + } + + // Good one, finally + try { + XMLReaderFactory.createXMLReader( + "tests.api.org.xml.sax.support.DoNothingXMLReader"); + } catch (SAXException e) { + throw new RuntimeException("Unexpected exception", e); + } + + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/BrokenInputStream.java b/xml/src/test/java/tests/api/org/xml/sax/support/BrokenInputStream.java new file mode 100644 index 0000000..daa36f9 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/BrokenInputStream.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Implements an InputStream what wraps another InputStream and throws an + * IOException after having read a specified number of bytes. Used for + * injecting IOExceptions on lower levels. + */ +public class BrokenInputStream extends InputStream { + + private InputStream stream; + + private int offset; + + public BrokenInputStream(InputStream stream, int offset) { + super(); + + this.stream = stream; + this.offset = offset; + } + + @Override + public int read() throws IOException { + if (offset == 0) { + throw new IOException("Injected exception"); + } + + offset--; + return stream.read(); + } + +}
\ No newline at end of file diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingParser.java new file mode 100644 index 0000000..6049cc6 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingParser.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Parser; + +import java.util.Locale; + +/** + * A SAX Parser that does nothing, but can be instantiated properly. + */ +@SuppressWarnings("deprecation") +public class DoNothingParser implements Parser { + + public void parse(InputSource source) { + } + + public void parse(String systemId) { + } + + public void setDocumentHandler(DocumentHandler handler) { + } + + public void setDTDHandler(DTDHandler handler) { + } + + public void setEntityResolver(EntityResolver resolver) { + } + + public void setErrorHandler(ErrorHandler handler) { + } + + public void setLocale(Locale locale) { + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingXMLReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingXMLReader.java new file mode 100644 index 0000000..8687bff --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingXMLReader.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +/** + * An XMLReader that does nothing, but can be instantiated properly. + */ +public class DoNothingXMLReader implements XMLReader { + + public ContentHandler getContentHandler() { + return null; + } + + public DTDHandler getDTDHandler() { + return null; + } + + public EntityResolver getEntityResolver() { + return null; + } + + public ErrorHandler getErrorHandler() { + return null; + } + + public boolean getFeature(String name) { + return false; + } + + public Object getProperty(String name) { + return null; + } + + public void parse(InputSource input) { + } + + public void parse(String systemId) { + } + + public void setContentHandler(ContentHandler handler) { + } + + public void setDTDHandler(DTDHandler handler) { + } + + public void setEntityResolver(EntityResolver resolver) { + } + + public void setErrorHandler(ErrorHandler handler) { + } + + public void setFeature(String name, boolean value) { + } + + public void setProperty(String name, Object value) { + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MethodLogger.java b/xml/src/test/java/tests/api/org/xml/sax/support/MethodLogger.java new file mode 100644 index 0000000..198172b --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/MethodLogger.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import java.util.ArrayList; +import java.util.List; + +/** + * A simple helper class that logs method calls by storing method names and + * parameter lists. Used as a foundation for various simple SAX handlers. + */ +public class MethodLogger { + + /** + * The names of the invoked methods, in order. + */ + private List<String> methods = new ArrayList<String>(); + + /** + * The parameter lists of the invoked methods, in order. + */ + private List<Object[]> argLists = new ArrayList<Object[]>(); + + /** + * Adds a method call with a variable list of arguments. + */ + public void add(String method, Object ... args) { + Object[] argsCopy = new Object[args.length]; + System.arraycopy(args, 0, argsCopy, 0, args.length); + + methods.add(method); + argLists.add(argsCopy); + } + + /** + * Returns the number of method invoked so far. + */ + public int size() { + return methods.size(); + } + + /** + * Returns the method name stored at the given index. + */ + public String getMethod(int index) { + return methods.get(index); + } + + /** + * Returns the name of the last method that was invoked. Returns null if no + * method calls have been logged so far. + */ + public String getMethod() { + return (size() == 0 ? null : getMethod(size() - 1)); + } + + /** + * Returns the argument array stored at the given index. May be empty, but + * not null. + */ + public Object[] getArgs(int index) { + return argLists.get(index); + } + + /** + * Returns the argument array of the last method that was invoked. Returns + * null if no method has been invoked so far. + */ + public Object[] getArgs() { + return (size() == 0 ? null : getArgs(size() - 1)); + } + + /** + * Clears the log. + */ + public void clear() { + methods.clear(); + argLists.clear(); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockFilter.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockFilter.java new file mode 100644 index 0000000..0b54bf8 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockFilter.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.helpers.XMLFilterImpl; + +/** + * A helper class that extends XMLFilterImpl, provides dummy feature/property + * management, and logs some method calls. + */ +public class MockFilter extends XMLFilterImpl { + + private MethodLogger logger; + + private Set<String> features = new HashSet<String>(); + + private Map<String, Object> properties = new HashMap<String, Object>(); + + public MockFilter(MethodLogger logger) { + super(); + this.logger = logger; + } + + @Override + public boolean getFeature(String name) throws SAXNotRecognizedException, + SAXNotSupportedException { + return features.contains(name); + } + + @Override + public Object getProperty(String name) throws SAXNotRecognizedException, + SAXNotSupportedException { + return properties.get(name); + } + + @Override + public void setFeature(String name, boolean value) { + if (value) { + features.add(name); + } else { + features.remove(name); + } + } + + @Override + public void setProperty(String name, Object value) throws SAXNotRecognizedException, + SAXNotSupportedException { + if (value == null) { + properties.remove(name); + } else { + properties.put(name, value); + } + } + + @Override + public void parse(InputSource input) throws SAXException, IOException { + logger.add("parse", input); + } + + @Override + public void parse(String systemId) throws SAXException, IOException { + logger.add("parse", systemId); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockHandler.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockHandler.java new file mode 100644 index 0000000..98b024a --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockHandler.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.AttributeList; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; +import org.xml.sax.ErrorHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.ext.LexicalHandler; + +/** + * A helper class that implements the various SAX callback interfaces and logs + * method calls. + */ +@SuppressWarnings("deprecation") +public class MockHandler implements ContentHandler, DTDHandler, DocumentHandler, + ErrorHandler, LexicalHandler { + + private MethodLogger logger; + + public MockHandler(MethodLogger logger) { + super(); + this.logger = logger; + } + + public void characters(char[] ch, int start, int length) throws SAXException { + logger.add("characters", ch, start, length); + } + + public void endDocument() throws SAXException { + logger.add("endDocument"); + } + + public void endElement(String name) throws SAXException { + logger.add("endElement", name); + } + + public void endElement(String uri, String localName, String name) throws SAXException { + logger.add("endElement", uri, localName, name); + } + + public void endPrefixMapping(String prefix) throws SAXException { + logger.add("endPrefixMapping", prefix); + } + + public void error(SAXParseException exception) throws SAXException { + logger.add("error", exception); + } + + public void fatalError(SAXParseException exception) throws SAXException { + logger.add("fatalError", exception); + } + + public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + logger.add("ignorableWhitespace", ch, start, length); + } + + public void notationDecl(String name, String publicId, String systemId) throws SAXException { + logger.add("notationDecl", name, publicId, systemId); + } + + public void processingInstruction(String target, String data) throws SAXException { + logger.add("processingInstruction", target, data); + } + + public void setDocumentLocator(Locator locator) { + logger.add("setDocumentLocator", locator); + } + + public void skippedEntity(String name) throws SAXException { + logger.add("skippedEntity", name); + } + + public void startDocument() throws SAXException { + logger.add("startDocument"); + } + + public void startElement(String name, AttributeList atts) throws SAXException { + logger.add("startElement", name, atts); + } + + public void startElement(String uri, String localName, String name, Attributes atts) + throws SAXException { + logger.add("startElement", uri, localName, name, atts); + } + + public void startPrefixMapping(String prefix, String uri) throws SAXException { + logger.add("startPrefixMapping", prefix, uri); + } + + public void unparsedEntityDecl(String name, String publicId, String systemId, + String notationName) throws SAXException { + logger.add("unparsedEntityDecl", name, publicId, systemId, notationName); + } + + public void warning(SAXParseException exception) throws SAXException { + logger.add("warning", exception); + } + + public void comment(char[] ch, int start, int length) throws SAXException { + logger.add("comment", ch, start, length); + } + + public void endCDATA() throws SAXException { + logger.add("endCDATA"); + } + + public void endDTD() throws SAXException { + logger.add("endDTD"); + } + + public void endEntity(String name) throws SAXException { + logger.add("endEntity", name); + } + + public void startCDATA() throws SAXException { + logger.add("startCDATA"); + } + + public void startDTD(String name, String publicId, String systemId) throws SAXException { + logger.add("startDTD", name, publicId, systemId); + } + + public void startEntity(String name) throws SAXException { + logger.add("startEntity", name); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockParser.java new file mode 100644 index 0000000..01520f8 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockParser.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import java.io.IOException; +import java.util.Locale; + +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Parser; +import org.xml.sax.SAXException; + +@SuppressWarnings("deprecation") +public class MockParser implements Parser { + + private MethodLogger logger; + + public MockParser(MethodLogger logger) { + super(); + this.logger = logger; + } + + public void parse(InputSource source) throws SAXException, IOException { + logger.add("parse", source); + } + + public void parse(String systemId) throws SAXException, IOException { + logger.add("parse", systemId); + } + + public void setDTDHandler(DTDHandler handler) { + logger.add("setDTDHandler", handler); + } + + public void setDocumentHandler(DocumentHandler handler) { + logger.add("setDocumentHandler", handler); + } + + public void setEntityResolver(EntityResolver resolver) { + logger.add("setEntityResolver", resolver); + } + + public void setErrorHandler(ErrorHandler handler) { + logger.add("setErrorHandler", handler); + } + + public void setLocale(Locale locale) throws SAXException { + logger.add("setLocale", locale); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockReader.java new file mode 100644 index 0000000..22a6a57 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockReader.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; + +/** + * A helper class that implements the SAX XMLReader interface and logs method + * calls. + */ +public class MockReader implements XMLReader { + + private MethodLogger logger; + + private ContentHandler contentHandler; + + private DTDHandler dtdHandler; + + private EntityResolver resolver; + + private ErrorHandler errorHandler; + + private Set<String> features = new HashSet<String>(); + + private Map<String, Object> properties = new HashMap<String, Object>(); + + public MockReader(MethodLogger logger) { + super(); + this.logger = logger; + } + + + public ContentHandler getContentHandler() { + return contentHandler; + } + + public DTDHandler getDTDHandler() { + return dtdHandler; + } + + public EntityResolver getEntityResolver() { + return resolver; + } + + public ErrorHandler getErrorHandler() { + return errorHandler; + } + + public boolean getFeature(String name) throws SAXNotRecognizedException, + SAXNotSupportedException { + return features.contains(name); + } + + public Object getProperty(String name) throws SAXNotRecognizedException, + SAXNotSupportedException { + return properties.get(name); + } + + public void parse(InputSource input) throws IOException, SAXException { + logger.add("parse", input); + } + + public void parse(String systemId) throws IOException, SAXException { + logger.add("parse", systemId); + } + + public void setContentHandler(ContentHandler handler) { + this.contentHandler = handler; + } + + public void setDTDHandler(DTDHandler handler) { + this.dtdHandler = handler; + } + + public void setEntityResolver(EntityResolver resolver) { + this.resolver = resolver; + } + + public void setErrorHandler(ErrorHandler handler) { + this.errorHandler = handler; + } + + public void setFeature(String name, boolean value) { + if (value) { + features.add(name); + } else { + features.remove(name); + } + } + + public void setProperty(String name, Object value) throws SAXNotRecognizedException, + SAXNotSupportedException { + if (value == null) { + properties.remove(name); + } else { + properties.put(name, value); + } + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockResolver.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockResolver.java new file mode 100644 index 0000000..ae0066e --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockResolver.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * A helper class for resolving entities. + */ +public class MockResolver implements EntityResolver { + + private Map<String, InputSource> entities = new HashMap<String, InputSource>(); + + public void addEntity(String publicId, String systemId, InputSource source) { + entities.put("[" + publicId + ":" + systemId + "]", source); + } + + public void removeEntity(String publicId, String systemId) { + entities.remove("[" + publicId + ":" + systemId + "]"); + } + + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + return entities.get("[" + publicId + ":" + systemId + "]"); + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessParser.java new file mode 100644 index 0000000..5aac9af --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessParser.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Parser; + +import java.util.Locale; + +/** + * A SAX Parser that can't be accessed. + */ +@SuppressWarnings("deprecation") +class NoAccessParser implements Parser { + + public void parse(InputSource source) { + } + + public void parse(String systemId) { + } + + public void setDocumentHandler(DocumentHandler handler) { + } + + public void setDTDHandler(DTDHandler handler) { + } + + public void setEntityResolver(EntityResolver resolver) { + } + + public void setErrorHandler(ErrorHandler handler) { + } + + public void setLocale(Locale locale) { + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessXMLReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessXMLReader.java new file mode 100644 index 0000000..b6a0a68 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessXMLReader.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +/** + * An XMLReader that is not accessible. + */ +class NoAccessXMLReader implements XMLReader { + + public ContentHandler getContentHandler() { + return null; + } + + public DTDHandler getDTDHandler() { + return null; + } + + public EntityResolver getEntityResolver() { + return null; + } + + public ErrorHandler getErrorHandler() { + return null; + } + + public boolean getFeature(String name) { + return false; + } + + public Object getProperty(String name) { + return null; + } + + public void parse(InputSource input) { + } + + public void parse(String systemId) { + } + + public void setContentHandler(ContentHandler handler) { + } + + public void setDTDHandler(DTDHandler handler) { + } + + public void setEntityResolver(EntityResolver resolver) { + } + + public void setErrorHandler(ErrorHandler handler) { + } + + public void setFeature(String name, boolean value) { + } + + public void setProperty(String name, Object value) { + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceParser.java new file mode 100644 index 0000000..8f1692f --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceParser.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Parser; + +import java.util.Locale; + +/** + * A SAX Parser that can be accessed, but not instantiated. + */ +@SuppressWarnings("deprecation") +public class NoInstanceParser implements Parser { + + public NoInstanceParser(int i) { + } + + public void parse(InputSource source) { + } + + public void parse(String systemId) { + } + + public void setDocumentHandler(DocumentHandler handler) { + } + + public void setDTDHandler(DTDHandler handler) { + } + + public void setEntityResolver(EntityResolver resolver) { + } + + public void setErrorHandler(ErrorHandler handler) { + } + + public void setLocale(Locale locale) { + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceXMLReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceXMLReader.java new file mode 100644 index 0000000..764c451 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceXMLReader.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +/** + * An XMLReader that is accessible, but can't be instantiated. + */ +public class NoInstanceXMLReader implements XMLReader { + + public NoInstanceXMLReader(int i) { + } + + public ContentHandler getContentHandler() { + return null; + } + + public DTDHandler getDTDHandler() { + return null; + } + + public EntityResolver getEntityResolver() { + return null; + } + + public ErrorHandler getErrorHandler() { + return null; + } + + public boolean getFeature(String name) { + return false; + } + + public Object getProperty(String name) { + return null; + } + + public void parse(InputSource input) { + } + + public void parse(String systemId) { + } + + public void setContentHandler(ContentHandler handler) { + } + + public void setDTDHandler(DTDHandler handler) { + } + + public void setEntityResolver(EntityResolver resolver) { + } + + public void setErrorHandler(ErrorHandler handler) { + } + + public void setFeature(String name, boolean value) { + } + + public void setProperty(String name, Object value) { + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassParser.java new file mode 100644 index 0000000..f178998 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassParser.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.DTDHandler; +import org.xml.sax.DocumentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; + +import java.util.Locale; + +/** + * A SAX Parser that does not implement the Parser interface. + */ +@SuppressWarnings("deprecation") +public class NoSubclassParser { + + public void parse(InputSource source) { + } + + public void parse(String systemId) { + } + + public void setDocumentHandler(DocumentHandler handler) { + } + + public void setDTDHandler(DTDHandler handler) { + } + + public void setEntityResolver(EntityResolver resolver) { + } + + public void setErrorHandler(ErrorHandler handler) { + } + + public void setLocale(Locale locale) { + } + +} diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassXMLReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassXMLReader.java new file mode 100644 index 0000000..acdbd88 --- /dev/null +++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassXMLReader.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.org.xml.sax.support; + +import org.xml.sax.ContentHandler; +import org.xml.sax.DTDHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +/** + * An XMLReader that does not implement the XMLReader interface. + */ +public class NoSubclassXMLReader implements XMLReader { + + public ContentHandler getContentHandler() { + return null; + } + + public DTDHandler getDTDHandler() { + return null; + } + + public EntityResolver getEntityResolver() { + return null; + } + + public ErrorHandler getErrorHandler() { + return null; + } + + public boolean getFeature(String name) { + return false; + } + + public Object getProperty(String name) { + return null; + } + + public void parse(InputSource input) { + } + + public void parse(String systemId) { + } + + public void setContentHandler(ContentHandler handler) { + } + + public void setDTDHandler(DTDHandler handler) { + } + + public void setEntityResolver(EntityResolver resolver) { + } + + public void setErrorHandler(ErrorHandler handler) { + } + + public void setFeature(String name, boolean value) { + } + + public void setProperty(String name, Object value) { + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/AllTests.java b/xml/src/test/java/tests/org/w3c/dom/AllTests.java new file mode 100644 index 0000000..a4299a7 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/AllTests.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.org.w3c.dom; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * This is autogenerated source file. Includes tests for package org.w3c.dom; + */ + +public class AllTests { + + public static void main(String[] args) { + junit.textui.TestRunner.run(AllTests.suite()); + } + + public static Test suite() { + TestSuite suite = tests.TestSuiteFactory.createTestSuite("All tests for package org.w3c.dom;"); + // $JUnit-BEGIN$ + + suite.addTestSuite(AttrGetOwnerElement.class); + suite.addTestSuite(CreateAttributeNS.class); + suite.addTestSuite(CreateDocument.class); + suite.addTestSuite(CreateDocumentType.class); + suite.addTestSuite(CreateElementNS.class); + suite.addTestSuite(DOMImplementationCreateDocument.class); + suite.addTestSuite(DOMImplementationCreateDocumentType.class); + suite.addTestSuite(DOMImplementationHasFeature.class); + suite.addTestSuite(DocumentCreateAttributeNS.class); + suite.addTestSuite(DocumentCreateElementNS.class); + suite.addTestSuite(DocumentGetElementsByTagnameNS.class); + suite.addTestSuite(DocumentGeteEementById.class); + suite.addTestSuite(DocumentImportNode.class); + suite.addTestSuite(DocumentTypeInternalSubset.class); + suite.addTestSuite(DocumentTypePublicId.class); + suite.addTestSuite(DocumentTypeSystemId.class); +// Is empty. Only test assumes validation. Leave disabled. +// suite.addTestSuite(ElementGetAttributeNS.class); + suite.addTestSuite(ElementGetAttributeNodeNS.class); + suite.addTestSuite(ElementGetElementsByTagNameNS.class); + suite.addTestSuite(ElementHasAttribute.class); + suite.addTestSuite(ElementHasAttributeNS.class); + suite.addTestSuite(ElementRemoveAttributeNS.class); + suite.addTestSuite(ElementSetAttributeNS.class); + suite.addTestSuite(ElementSetAttributeNodeNS.class); + suite.addTestSuite(GetAttributeNS.class); + suite.addTestSuite(GetAttributeNodeNS.class); + suite.addTestSuite(GetElementById.class); + suite.addTestSuite(GetElementsByTagNameNS.class); + suite.addTestSuite(GetNamedItemNS.class); +// Is empty. Only test assumes validation. Leave disabled. +// suite.addTestSuite(HCEntitiesRemoveNamedItemNS.class); +// Is empty. Only test assumes validation. Leave disabled. +// suite.addTestSuite(HCEntitiesSetNamedItemNS.class); + suite.addTestSuite(HCNamedNodeMapInvalidType.class); + suite.addTestSuite(HCNodeDocumentFragmentNormalize.class); +// Is empty. Only test assumes validation. Leave disabled. +// suite.addTestSuite(HCNotationsRemoveNamedItemNS.class); +// Is empty. Only test assumes validation. Leave disabled. +// suite.addTestSuite(HCNotationsSetNamedItemNS.class); + suite.addTestSuite(HasAttribute.class); + suite.addTestSuite(HasAttributeNS.class); + suite.addTestSuite(HasAttributes.class); + suite.addTestSuite(ImportNode.class); + suite.addTestSuite(InternalSubset.class); + suite.addTestSuite(IsSupported.class); + suite.addTestSuite(LocalName.class); + suite.addTestSuite(NamedNodeMapGetNamedItemNS.class); + suite.addTestSuite(NamedNodeMapRemoveNamedItemNS.class); + suite.addTestSuite(NamedNodeMapSetNamedItemNS.class); + suite.addTestSuite(NamespaceURI.class); + suite.addTestSuite(NodeGetLocalName.class); + suite.addTestSuite(NodeGetNamespaceURI.class); + suite.addTestSuite(NodeGetOwnerDocument.class); + suite.addTestSuite(NodeGetPrefix.class); + suite.addTestSuite(NodeHasAttributes.class); + suite.addTestSuite(NodeIsSupported.class); + suite.addTestSuite(NodeNormalize.class); + suite.addTestSuite(NodeSetPrefix.class); + suite.addTestSuite(Normalize.class); + suite.addTestSuite(OwnerDocument.class); + suite.addTestSuite(OwnerElement.class); + suite.addTestSuite(Prefix.class); + suite.addTestSuite(PublicId.class); +// Is empty. Only test assumes validation. Leave disabled. +// suite.addTestSuite(RemoveAttributeNS.class); + suite.addTestSuite(RemoveNamedItemNS.class); + suite.addTestSuite(SetAttributeNS.class); + suite.addTestSuite(SetAttributeNodeNS.class); + suite.addTestSuite(SetNamedItemNS.class); + suite.addTestSuite(SystemId.class); + // $JUnit-END$ + return suite; + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/AttrGetOwnerElement.java b/xml/src/test/java/tests/org/w3c/dom/AttrGetOwnerElement.java new file mode 100644 index 0000000..bb42121 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/AttrGetOwnerElement.java @@ -0,0 +1,156 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.NamedNodeMap; + +import javax.xml.parsers.DocumentBuilder; + +@TestTargetClass(Attr.class) +public final class AttrGetOwnerElement extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception " + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + +// Assumes validation. +// public void testGetOwnerElement1() throws Throwable { +// Document doc; +// Attr attr; +// Element element; +// Element ownerElement; +// String ownerElementName; +// NodeList elementList; +// NamedNodeMap attributes; +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// +// elementList = doc.getElementsByTagNameNS("http://www.nist.gov", +// "employee"); +// element = (Element) elementList.item(1); +// attributes = element.getAttributes(); +// attr = (Attr) attributes.getNamedItemNS(nullNS, "defaultAttr"); +// ownerElement = attr.getOwnerElement(); +// ownerElementName = ownerElement.getNodeName(); +// assertEquals("attrgetownerelement01", "emp:employee", ownerElementName); +// +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify that getOwnerElement returns null if an attribute is not in use.", + method = "getOwnerElement", + args = {} + ) + public void testGetOwnerElement2() throws Throwable { + Document doc; + Element element; + Element ownerElement; + String ownerElementName; + Attr attr; + + doc = (Document) load("staffNS", builder); + element = doc.createElement("root"); + attr = doc.createAttributeNS("http://www.w3.org/DOM/L1", "L1:att"); + element.setAttributeNodeNS(attr); + ownerElement = attr.getOwnerElement(); + ownerElementName = ownerElement.getNodeName(); + assertEquals("attrgetownerelement02", "root", ownerElementName); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getOwnerElement returns null if an attribute is not in use.", + method = "getOwnerElement", + args = {} + ) + public void testGetOwnerElement3() throws Throwable { + Document doc; + Node ownerElement; + Attr attr; + doc = (Document) load("staffNS", builder); + attr = doc.createAttributeNS("http://www.w3.org/DOM", "dom:attr"); + ownerElement = attr.getOwnerElement(); + assertNull("attrgetownerelement03", ownerElement); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getOwnerElement returns null if an attribute is not in use.", + method = "getOwnerElement", + args = {} + ) + public void testGetOwnerElement4() throws Throwable { + Document doc; + Document docImp; + Node ownerElement; + Element element; + Attr attr; + Attr attrImp; + NodeList addresses; + + doc = (Document) load("staffNS", builder); + docImp = (Document) load("staff", builder); + + addresses = doc + .getElementsByTagNameNS("http://www.nist.gov", "address"); + element = (Element) addresses.item(1); + assertNotNull("empAddressNotNull", element); + attr = element.getAttributeNodeNS("http://www.nist.gov", "zone"); + attrImp = (Attr) docImp.importNode(attr, true); + ownerElement = attrImp.getOwnerElement(); + assertNull("attrgetownerelement04", ownerElement); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify that getOwnerElement returns null if an attribute is not in use.", + method = "getOwnerElement", + args = {} + ) + public void testGetOwnerElement5() throws Throwable { + Document doc; + Node element; + Element ownerElement; + Element parentElement; + NodeList elementList; + String ownerElementName; + Attr attr; + + NamedNodeMap nodeMap; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = elementList.item(1); + parentElement = (Element) element.getParentNode(); + nodeMap = element.getAttributes(); + parentElement.removeChild(element); + attr = (Attr) nodeMap.getNamedItemNS(nullNS, "street"); + ownerElement = attr.getOwnerElement(); + ownerElementName = ownerElement.getNodeName(); + assertEquals("attrgetownerelement05", "address", ownerElementName); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/CreateAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/CreateAttributeNS.java new file mode 100644 index 0000000..c7e0d34 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/CreateAttributeNS.java @@ -0,0 +1,229 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.DOMException; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +@TestTargetClass(Document.class) +public final class CreateAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies NAMESPACE_ERR exception code.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS1() throws Throwable { + String namespaceURI = "http://www.ecommerce.org/"; + String malformedName = "prefix::local"; + Document doc; + + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createAttributeNS(namespaceURI, malformedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies createAttributeNS method with null as the fisrt parameter.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS2() throws Throwable { + String namespaceURI = null; + + String qualifiedName = "prefix:local"; + Document doc; + + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createAttributeNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createAttributeNS throws DOMException.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS3() throws Throwable { + String namespaceURI = "http://www.wedding.com/"; + String qualifiedName; + Document doc; + + List<String> illegalQNames = new ArrayList<String>(); + illegalQNames.add("person:{"); + illegalQNames.add("person:}"); + illegalQNames.add("person:~"); + illegalQNames.add("person:'"); + illegalQNames.add("person:!"); + illegalQNames.add("person:@"); + illegalQNames.add("person:#"); + illegalQNames.add("person:$"); + illegalQNames.add("person:%"); + illegalQNames.add("person:^"); + illegalQNames.add("person:&"); + illegalQNames.add("person:*"); + illegalQNames.add("person:("); + illegalQNames.add("person:)"); + illegalQNames.add("person:+"); + illegalQNames.add("person:="); + illegalQNames.add("person:["); + illegalQNames.add("person:]"); + illegalQNames.add("person:\\"); + illegalQNames.add("person:/"); + illegalQNames.add("person:;"); + illegalQNames.add("person:`"); + illegalQNames.add("person:<"); + illegalQNames.add("person:>"); + illegalQNames.add("person:,"); + illegalQNames.add("person:a "); + illegalQNames.add("person:\""); + + doc = (Document) load("staffNS", builder); + for (int indexN10090 = 0; indexN10090 < illegalQNames.size(); indexN10090++) { + qualifiedName = (String) illegalQNames.get(indexN10090); + { + boolean success = false; + try { + doc.createAttributeNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("throw_INVALID_CHARACTER_ERR", success); + } + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify exceptions.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS4() throws Throwable { + String namespaceURI = "http://www.w3.org/XML/1998/namespaces"; + String qualifiedName = "xml:attr1"; + Document doc; + + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createAttributeNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify exceptions.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS5() throws Throwable { + String namespaceURI = "http://www.ecommerce.org/"; + String qualifiedName = "econm:local"; + Document doc; + Attr newAttr; + String attrName; + doc = (Document) load("staffNS", builder); + newAttr = doc.createAttributeNS(namespaceURI, qualifiedName); + attrName = newAttr.getName(); + assertEquals("throw_Equals", qualifiedName, attrName); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS6() throws Throwable { + String namespaceURI = "http://www.example.com/"; + Document doc; + + doc = (Document) load("hc_staff", builder); + + boolean success = false; + try { + doc.createAttributeNS(namespaceURI, ""); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_INVALID_CHARACTER_ERR", success); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/CreateDocument.java b/xml/src/test/java/tests/org/w3c/dom/CreateDocument.java new file mode 100644 index 0000000..157b394 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/CreateDocument.java @@ -0,0 +1,317 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "createDocument(namespaceURI,qualifiedName,doctype)" method for a + * DOMImplementation should raise NAMESPACE_ERR DOMException if parameter + * qualifiedName is malformed. + * + * Retrieve the DOMImplementation on the XMLNS Document. Invoke method + * createDocument(namespaceURI,qualifiedName,doctype) on the retrieved + * DOMImplementation with namespaceURI being the literal string + * "http://www.ecommerce.org/", qualifiedName as "prefix::local", and doctype as + * null. Method should raise NAMESPACE_ERR DOMException. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('Level-2-Core-DOM-createDocument')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('Level-2-Core-DOM-createDocument')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])</a> + */ +@TestTargetClass(DOMImplementation.class) +public final class CreateDocument extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument1() throws Throwable { + String namespaceURI = "http://www.ecommerce.org/"; + String malformedName = "prefix::local"; + Document doc; + DocumentType docType = null; + + DOMImplementation domImpl; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + + boolean success = false; + try { + domImpl.createDocument(namespaceURI, malformedName, docType); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument2() throws Throwable { + String namespaceURI = null; + + String qualifiedName = "k:local"; + Document doc; + DocumentType docType = null; + + DOMImplementation domImpl; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + + boolean success = false; + try { + domImpl.createDocument(namespaceURI, qualifiedName, docType); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + + } + +// public void testCreateDocument3() throws Throwable { +// String namespaceURI = "http://www.ecommerce.org/schema"; +// String qualifiedName = "namespaceURI:x"; +// Document doc; +// DocumentType docType; +// DOMImplementation domImpl; +// +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// domImpl = doc.getImplementation(); +// +// boolean success = false; +// try { +// domImpl.createDocument(namespaceURI, qualifiedName, docType); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.WRONG_DOCUMENT_ERR); +// } +// assertTrue("throw_WRONG_DOCUMENT_ERR", success); +// +// } + +// public void testCreateDocument4() throws Throwable { +// String namespaceURI = "http://www.ecommerce.org/schema"; +// String qualifiedName = "namespaceURI:x"; +// Document doc; +// DocumentType docType; +// DOMImplementation domImpl; +// Document aNewDoc; +// doc = (Document) load("staffNS", builder); +// aNewDoc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// domImpl = aNewDoc.getImplementation(); +// +// boolean success = false; +// try { +// aNewDoc = domImpl.createDocument(namespaceURI, qualifiedName, +// docType); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.WRONG_DOCUMENT_ERR); +// } +// assertTrue("throw_WRONG_DOCUMENT_ERR", success); +// +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument5() throws Throwable { + String namespaceURI = "http://www.ecommerce.org/schema"; + String qualifiedName; + Document doc; + DocumentType docType = null; + + DOMImplementation domImpl; + + List<String> illegalQNames = new ArrayList<String>(); + illegalQNames.add("namespaceURI:{"); + illegalQNames.add("namespaceURI:}"); + illegalQNames.add("namespaceURI:~"); + illegalQNames.add("namespaceURI:'"); + illegalQNames.add("namespaceURI:!"); + illegalQNames.add("namespaceURI:@"); + illegalQNames.add("namespaceURI:#"); + illegalQNames.add("namespaceURI:$"); + illegalQNames.add("namespaceURI:%"); + illegalQNames.add("namespaceURI:^"); + illegalQNames.add("namespaceURI:&"); + illegalQNames.add("namespaceURI:*"); + illegalQNames.add("namespaceURI:("); + illegalQNames.add("namespaceURI:)"); + illegalQNames.add("namespaceURI:+"); + illegalQNames.add("namespaceURI:="); + illegalQNames.add("namespaceURI:["); + illegalQNames.add("namespaceURI:]"); + illegalQNames.add("namespaceURI:\\"); + illegalQNames.add("namespaceURI:/"); + illegalQNames.add("namespaceURI:;"); + illegalQNames.add("namespaceURI:`"); + illegalQNames.add("namespaceURI:<"); + illegalQNames.add("namespaceURI:>"); + illegalQNames.add("namespaceURI:,"); + illegalQNames.add("namespaceURI:a "); + illegalQNames.add("namespaceURI:\""); + + doc = (Document) load("staffNS", builder); + for (int indexN1009A = 0; indexN1009A < illegalQNames.size(); indexN1009A++) { + qualifiedName = (String) illegalQNames.get(indexN1009A); + domImpl = doc.getImplementation(); + + boolean success = false; + try { + domImpl.createDocument(namespaceURI, qualifiedName, docType); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("throw_INVALID_CHARACTER_ERR", success); + + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument6() throws Throwable { + String namespaceURI = "http://ecommerce.org/schema"; + String qualifiedName = "xml:local"; + Document doc; + DocumentType docType = null; + + DOMImplementation domImpl; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + + boolean success = false; + try { + domImpl.createDocument(namespaceURI, qualifiedName, docType); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument7() throws Throwable { + String namespaceURI = "http://www.ecommerce.org/schema"; + String qualifiedName = "y:x"; + Document doc; + DocumentType docType = null; + + DOMImplementation domImpl; + Document aNewDoc; + String nodeName; + String nodeValue; + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + aNewDoc = domImpl.createDocument(namespaceURI, qualifiedName, docType); + nodeName = aNewDoc.getNodeName(); + nodeValue = aNewDoc.getNodeValue(); + assertEquals("nodeName", "#document", nodeName); + assertNull("nodeValue", nodeValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument8() throws Throwable { + String namespaceURI = "http://www.example.org/schema"; + DocumentType docType = null; + + DOMImplementation domImpl; + + domImpl = builder.getDOMImplementation(); + + boolean success = false; + try { + domImpl.createDocument(namespaceURI, "", docType); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/CreateDocumentType.java b/xml/src/test/java/tests/org/w3c/dom/CreateDocumentType.java new file mode 100644 index 0000000..c5061b8 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/CreateDocumentType.java @@ -0,0 +1,222 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.DOMException; +import org.w3c.dom.DocumentType; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "createDocumentType(qualifiedName,publicId,systemId)" method for a + * DOMImplementation should raise NAMESPACE_ERR DOMException if qualifiedName is + * malformed. + * + * Retrieve the DOMImplementation on the XMLNS Document. Invoke method + * createDocumentType(qualifiedName,publicId,systemId) on the retrieved + * DOMImplementation with qualifiedName being the literal string + * "prefix::local", publicId as "STAFF", and systemId as "staff". Method should + * raise NAMESPACE_ERR DOMException. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocType">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocType</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('Level-2-Core-DOM-createDocType')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('Level-2-Core-DOM-createDocType')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])</a> + */ +@TestTargetClass(DOMImplementation.class) +public final class CreateDocumentType extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocumentType", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testCreateDocumentType1() throws Throwable { + String publicId = "STAFF"; + String systemId = "staff.xml"; + String malformedName = "prefix::local"; + Document doc; + DOMImplementation domImpl; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + + { + boolean success = false; + try { + domImpl.createDocumentType(malformedName, publicId, systemId); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocumentType", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testCreateDocumentType2() throws Throwable { + String publicId = "http://www.localhost.com/"; + String systemId = "myDoc.dtd"; + String qualifiedName; + Document doc; + + DOMImplementation domImpl; + List<String> illegalQNames = new ArrayList<String>(); + illegalQNames.add("edi:{"); + illegalQNames.add("edi:}"); + illegalQNames.add("edi:~"); + illegalQNames.add("edi:'"); + illegalQNames.add("edi:!"); + illegalQNames.add("edi:@"); + illegalQNames.add("edi:#"); + illegalQNames.add("edi:$"); + illegalQNames.add("edi:%"); + illegalQNames.add("edi:^"); + illegalQNames.add("edi:&"); + illegalQNames.add("edi:*"); + illegalQNames.add("edi:("); + illegalQNames.add("edi:)"); + illegalQNames.add("edi:+"); + illegalQNames.add("edi:="); + illegalQNames.add("edi:["); + illegalQNames.add("edi:]"); + illegalQNames.add("edi:\\"); + illegalQNames.add("edi:/"); + illegalQNames.add("edi:;"); + illegalQNames.add("edi:`"); + illegalQNames.add("edi:<"); + illegalQNames.add("edi:>"); + illegalQNames.add("edi:,"); + illegalQNames.add("edi:a "); + illegalQNames.add("edi:\""); + + doc = (Document) load("staffNS", builder); + for (int indexN1009A = 0; indexN1009A < illegalQNames.size(); indexN1009A++) { + qualifiedName = (String) illegalQNames.get(indexN1009A); + domImpl = doc.getImplementation(); + + { + boolean success = false; + try { + domImpl.createDocumentType(qualifiedName, publicId, + systemId); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("throw_INVALID_CHARACTER_ERR", success); + } + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocumentType", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testCreateDocumentType3() throws Throwable { + + String qualifiedName = "prefix:myDoc"; + String publicId = "http://www.localhost.com"; + String systemId = "myDoc.dtd"; + Document doc; + DOMImplementation domImpl; + DocumentType newType = null; + + String nodeName; + String nodeValue; + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + newType = domImpl.createDocumentType(qualifiedName, publicId, systemId); + nodeName = newType.getNodeName(); + assertEquals("nodeName", "prefix:myDoc", nodeName); + nodeValue = newType.getNodeValue(); + assertNull("nodeValue", nodeValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify null as parameters.", + method = "createDocumentType", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testCreateDocumentType4() throws Throwable { + String publicId = "http://www.example.com/"; + String systemId = "myDoc.dtd"; + + DOMImplementation domImpl; + domImpl = builder.getDOMImplementation(); + + { + boolean success = false; + try { + domImpl.createDocumentType("", publicId, systemId); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/CreateElementNS.java b/xml/src/test/java/tests/org/w3c/dom/CreateElementNS.java new file mode 100644 index 0000000..8d8bb4d --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/CreateElementNS.java @@ -0,0 +1,251 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.DOMException; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "createElementNS(namespaceURI,qualifiedName)" method for a Document + * should raise NAMESPACE_ERR DOMException if qualifiedName is malformed. + * + * Invoke method createElementNS(namespaceURI,qualifiedName) on the XMLNS + * Document with namespaceURI being the literal string + * "http://www.ecommerce.org/", and qualifiedName as "prefix::local". Method + * should raise NAMESPACE_ERR DOMException. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrElNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrElNS</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-DocCrElNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-DocCrElNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])</a> + */ +@TestTargetClass(Document.class) +public final class CreateElementNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify null as a parameters, and other types of DOMException.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS1() throws Throwable { + String namespaceURI = "http://www.ecommerce.org/"; + String malformedName = "prefix::local"; + Document doc; + + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createElementNS(namespaceURI, malformedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify null as a parameters, and other types of DOMException.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS2() throws Throwable { + String namespaceURI = null; + + String qualifiedName = "prefix:local"; + Document doc; + + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createElementNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify null as a parameters, and other types of DOMException.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS3() throws Throwable { + String namespaceURI = "http://www.wedding.com/"; + String qualifiedName; + Document doc; + + List<String> illegalQNames = new ArrayList<String>(); + illegalQNames.add("person:{"); + illegalQNames.add("person:}"); + illegalQNames.add("person:~"); + illegalQNames.add("person:'"); + illegalQNames.add("person:!"); + illegalQNames.add("person:@"); + illegalQNames.add("person:#"); + illegalQNames.add("person:$"); + illegalQNames.add("person:%"); + illegalQNames.add("person:^"); + illegalQNames.add("person:&"); + illegalQNames.add("person:*"); + illegalQNames.add("person:("); + illegalQNames.add("person:)"); + illegalQNames.add("person:+"); + illegalQNames.add("person:="); + illegalQNames.add("person:["); + illegalQNames.add("person:]"); + illegalQNames.add("person:\\"); + illegalQNames.add("person:/"); + illegalQNames.add("person:;"); + illegalQNames.add("person:`"); + illegalQNames.add("person:<"); + illegalQNames.add("person:>"); + illegalQNames.add("person:,"); + illegalQNames.add("person:a "); + illegalQNames.add("person:\""); + + doc = (Document) load("staffNS", builder); + for (int indexN10098 = 0; indexN10098 < illegalQNames.size(); indexN10098++) { + qualifiedName = (String) illegalQNames.get(indexN10098); + + { + boolean success = false; + try { + doc.createElementNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("throw_INVALID_CHARACTER_ERR", success); + } + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify null as a parameters, and other types of DOMException.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS4() throws Throwable { + String namespaceURI = "http://www.w3.org/XML/1998/namespaces"; + String qualifiedName = "xml:element1"; + Document doc; + + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createElementNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify null as a parameters, and other types of DOMException.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS5() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String qualifiedName = "gov:faculty"; + Document doc; + Element newElement; + String elementName; + doc = (Document) load("staffNS", builder); + newElement = doc.createElementNS(namespaceURI, qualifiedName); + elementName = newElement.getTagName(); + assertEquals("throw_Equals", qualifiedName, elementName); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify null as a parameters, and other types of DOMException.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS6() throws Throwable { + String namespaceURI = "http://www.example.com/"; + + Document doc; + + doc = (Document) load("hc_staff", builder); + + { + boolean success = false; + try { + doc.createElementNS(namespaceURI, ""); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMDocumentBuilderFactory.java b/xml/src/test/java/tests/org/w3c/dom/DOMDocumentBuilderFactory.java new file mode 100644 index 0000000..d28b2d7 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DOMDocumentBuilderFactory.java @@ -0,0 +1,94 @@ +package tests.org.w3c.dom; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +public class DOMDocumentBuilderFactory { + /** + * Parser configuration + */ + private DocumentBuilderSetting[] settings = null; + + private DocumentBuilder builder = null; + + private DocumentBuilderFactory factory = null; + + public DOMDocumentBuilderFactory(DocumentBuilderSetting[] settings) { + if (settings == null) { + settings = new DocumentBuilderSetting[0]; + } else { + settings = (DocumentBuilderSetting[]) settings.clone(); + } + + factory = DocumentBuilderFactory.newInstance(); + + if (factory == null) { + throw new RuntimeException("DocumentBuilderFactory must not be null"); + } + + if (settings != null) { + for (int i = 0; i < settings.length; i++) { + settings[i].applySetting(factory); + } + } + try { + builder = factory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } + + if (builder == null) { + throw new RuntimeException("DocumentBuilder must not be null"); + } + + } + + public DocumentBuilder getBuilder() { + return builder; + } + + public boolean hasFeature(String feature, String version) { + return builder.getDOMImplementation().hasFeature(feature, version); + } + + public boolean isCoalescing() { + return factory.isCoalescing(); + } + + public boolean isExpandEntityReferences() { + return factory.isExpandEntityReferences(); + } + + public boolean isIgnoringElementContentWhitespace() { + return factory.isIgnoringElementContentWhitespace(); + } + + public boolean isNamespaceAware() { + return factory.isNamespaceAware(); + } + + public boolean isValidating() { + return factory.isValidating(); + } + + public static DocumentBuilderSetting[] getConfiguration1() { + return new DocumentBuilderSetting[] { + DocumentBuilderSetting.notCoalescing, + DocumentBuilderSetting.notExpandEntityReferences, + DocumentBuilderSetting.notIgnoringElementContentWhitespace, + DocumentBuilderSetting.notNamespaceAware, + DocumentBuilderSetting.notValidating }; + } + + public static DocumentBuilderSetting[] getConfiguration2() { + return new DocumentBuilderSetting[] { + DocumentBuilderSetting.notCoalescing, + DocumentBuilderSetting.notExpandEntityReferences, + DocumentBuilderSetting.notIgnoringElementContentWhitespace, + DocumentBuilderSetting.namespaceAware, + DocumentBuilderSetting.notValidating }; + + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocument.java b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocument.java new file mode 100644 index 0000000..d2650a4 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocument.java @@ -0,0 +1,177 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The createDocument method with valid arguments, should create a DOM Document + * of the specified type. + * + * Call the createDocument on this DOMImplementation with createDocument + * ("http://www.w3.org/DOMTest/L2",see the array below for valid QNames,null). + * Check if the returned Document object is is empty with no Document Element. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument</a> + */ +@TestTargetClass(DOMImplementation.class) +public final class DOMImplementationCreateDocument extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument3() throws Throwable { + Document doc; + DOMImplementation domImpl; + Document newDoc; + DocumentType docType = null; + + String namespaceURI = "http://www.w3.org/DOMTest/L2"; + String qualifiedName; + List<String> qualifiedNames = new ArrayList<String>(); + qualifiedNames.add("_:_"); + qualifiedNames.add("_:h0"); + qualifiedNames.add("_:test"); + qualifiedNames.add("l_:_"); + qualifiedNames.add("ns:_0"); + qualifiedNames.add("ns:a0"); + qualifiedNames.add("ns0:test"); + qualifiedNames.add("a.b:c"); + qualifiedNames.add("a-b:c"); + qualifiedNames.add("a-b:c"); + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + for (int indexN1006B = 0; indexN1006B < qualifiedNames.size(); indexN1006B++) { + qualifiedName = (String) qualifiedNames.get(indexN1006B); + newDoc = domImpl.createDocument(namespaceURI, qualifiedName, + docType); + assertNotNull("domimplementationcreatedocument03", newDoc); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument4() throws Throwable { + Document doc; + DOMImplementation domImpl; + + String namespaceURI = null; + + String qualifiedName = "dom:root"; + DocumentType docType = null; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + + { + boolean success = false; + try { + domImpl.createDocument(namespaceURI, qualifiedName, docType); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("domimplementationcreatedocument04", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument5() throws Throwable { + Document doc; + DOMImplementation domImpl; + + String namespaceURI = "http://www.w3.org/xml/1998/namespace"; + String qualifiedName = "xml:root"; + DocumentType docType = null; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + + { + boolean success = false; + try { + domImpl.createDocument(namespaceURI, qualifiedName, docType); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("domimplementationcreatedocument05", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "createDocument", + args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class} + ) + public void testCreateDocument7() throws Throwable { + Document doc; + DOMImplementation domImpl; + + String namespaceURI = "http://www.w3.org/DOMTest/level2"; + DocumentType docType = null; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + + { + boolean success = false; + try { + domImpl.createDocument(namespaceURI, ":", docType); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("domimplementationcreatedocument07", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocumentType.java b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocumentType.java new file mode 100644 index 0000000..286e75d --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocumentType.java @@ -0,0 +1,208 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method createDocumentType with valid values for qualifiedName, publicId + * and systemId should create an empty DocumentType node. + * + * Invoke createDocument on this DOMImplementation with a valid qualifiedName + * and different publicIds and systemIds. Check if the the DocumentType node was + * created with its ownerDocument attribute set to null. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument</a> + */ +@TestTargetClass(DOMImplementation.class) +public final class DOMImplementationCreateDocumentType extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "createDocumentType", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testCreateDocumentType1() throws Throwable { + Document doc; + DOMImplementation domImpl; + DocumentType newDocType; + Document ownerDocument; + String qualifiedName = "test:root"; + String publicId; + String systemId; + List<String> publicIds = new ArrayList<String>(); + publicIds.add("1234"); + publicIds.add("test"); + + List<String> systemIds = new ArrayList<String>(); + systemIds.add(""); + systemIds.add("test"); + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + for (int indexN1005D = 0; indexN1005D < publicIds.size(); indexN1005D++) { + publicId = (String) publicIds.get(indexN1005D); + for (int indexN10061 = 0; indexN10061 < systemIds.size(); indexN10061++) { + systemId = (String) systemIds.get(indexN10061); + newDocType = domImpl.createDocumentType(qualifiedName, + publicId, systemId); + assertNotNull( + "domimplementationcreatedocumenttype01_newDocType", + newDocType); + ownerDocument = newDocType.getOwnerDocument(); + assertNull( + "domimplementationcreatedocumenttype01_ownerDocument", + ownerDocument); + } + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "createDocumentType", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testCreateDocumentType2() throws Throwable { + Document doc; + DOMImplementation domImpl; + DocumentType newDocType; + Document ownerDocument; + String publicId = "http://www.w3.org/DOM/Test/dom2.dtd"; + String systemId = "dom2.dtd"; + String qualifiedName; + List<String> qualifiedNames = new ArrayList<String>(); + qualifiedNames.add("_:_"); + qualifiedNames.add("_:h0"); + qualifiedNames.add("_:test"); + qualifiedNames.add("_:_."); + qualifiedNames.add("_:a-"); + qualifiedNames.add("l_:_"); + qualifiedNames.add("ns:_0"); + qualifiedNames.add("ns:a0"); + qualifiedNames.add("ns0:test"); + qualifiedNames.add("ns:EEE."); + qualifiedNames.add("ns:_-"); + qualifiedNames.add("a.b:c"); + qualifiedNames.add("a-b:c.j"); + qualifiedNames.add("a-b:c"); + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + for (int indexN10077 = 0; indexN10077 < qualifiedNames.size(); indexN10077++) { + qualifiedName = (String) qualifiedNames.get(indexN10077); + newDocType = domImpl.createDocumentType(qualifiedName, publicId, + systemId); + assertNotNull("domimplementationcreatedocumenttype02_newDocType", + newDocType); + ownerDocument = newDocType.getOwnerDocument(); + assertNull("domimplementationcreatedocumenttype02_ownerDocument", + ownerDocument); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "createDocumentType", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testCreateDocumentType4() throws Throwable { + Document doc; + DOMImplementation domImpl; + DocumentType newDocType; + Document ownerDocument; + String publicId = "http://www.w3.org/DOM/Test/dom2.dtd"; + String systemId = "dom2.dtd"; + String qualifiedName; + List<String> qualifiedNames = new ArrayList<String>(); + qualifiedNames.add("_:_"); + qualifiedNames.add("_:h0"); + qualifiedNames.add("_:test"); + qualifiedNames.add("_:_."); + qualifiedNames.add("_:a-"); + qualifiedNames.add("l_:_"); + qualifiedNames.add("ns:_0"); + qualifiedNames.add("ns:a0"); + qualifiedNames.add("ns0:test"); + qualifiedNames.add("ns:EEE."); + qualifiedNames.add("ns:_-"); + qualifiedNames.add("a.b:c"); + qualifiedNames.add("a-b:c.j"); + qualifiedNames.add("a-b:c"); + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + for (int indexN10077 = 0; indexN10077 < qualifiedNames.size(); indexN10077++) { + qualifiedName = (String) qualifiedNames.get(indexN10077); + newDocType = domImpl.createDocumentType(qualifiedName, publicId, + systemId); + assertNotNull("domimplementationcreatedocumenttype02_newDocType", + newDocType); + ownerDocument = newDocType.getOwnerDocument(); + assertNull("domimplementationcreatedocumenttype02_ownerDocument", + ownerDocument); + } + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMImplementationHasFeature.java b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationHasFeature.java new file mode 100644 index 0000000..257555b --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationHasFeature.java @@ -0,0 +1,147 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "feature" parameter in the "hasFeature(feature,version)" method is the + * package name of the feature. Legal values are XML and HTML and CORE. (Test + * for feature core, lower case) + * + * Retrieve the entire DOM document and invoke its "getImplementation()" method. + * This should create a DOMImplementation object whose "hasFeature(feature, + * version)" method is invoked with feature equal to "core". The method should + * return a boolean "true". + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-5CED94D7">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-5CED94D7</a> + */ +@TestTargetClass(DOMImplementation.class) +public final class DOMImplementationHasFeature extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that hasFeature returns true value.", + method = "hasFeature", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasFeatureCore() throws Throwable { + Document doc; + DOMImplementation domImpl; + boolean state; + doc = (Document) load("staff", builder); + domImpl = doc.getImplementation(); + state = domImpl.hasFeature("core", "2.0"); + assertTrue("domimplementationFeaturecoreAssert", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that hasFeature returns true value.", + method = "hasFeature", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasFeatureXml() throws Throwable { + Document doc; + DOMImplementation domImpl; + boolean state; + doc = (Document) load("staff", builder); + domImpl = doc.getImplementation(); + state = domImpl.hasFeature("xml", "2.0"); + assertTrue("domimplementationFeaturexmlVersion2Assert", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify that hasFeature method returns false.", + method = "hasFeature", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasFeature1() throws Throwable { + Document doc; + DOMImplementation domImpl; + String version = ""; + String version1 = "1.0"; + String version2 = "2.0"; + String featureCore; + String featureXML; + boolean success; + List<String> featuresXML = new ArrayList<String>(); + featuresXML.add("XML"); + featuresXML.add("xmL"); + + List<String> featuresCore = new ArrayList<String>(); + featuresCore.add("Core"); + featuresCore.add("CORE"); + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + for (int indexN10063 = 0; indexN10063 < featuresXML.size(); indexN10063++) { + featureXML = (String) featuresXML.get(indexN10063); + success = domImpl.hasFeature(featureXML, version); + assertTrue("domimplementationhasfeature01_XML_1", success); + success = domImpl.hasFeature(featureXML, version1); + assertTrue("domimplementationhasfeature01_XML_2", success); + } + for (int indexN1007C = 0; indexN1007C < featuresCore.size(); indexN1007C++) { + featureCore = (String) featuresCore.get(indexN1007C); + success = domImpl.hasFeature(featureCore, version); + assertTrue("domimplementationhasfeature01_Core_1", success); + success = domImpl.hasFeature(featureCore, version1); + success = domImpl.hasFeature(featureCore, version2); + assertTrue("domimplementationhasfeature01_Core_3", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that hasFeature method returns false.", + method = "hasFeature", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasFeature2() throws Throwable { + Document doc; + DOMImplementation domImpl; + boolean success; + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + success = domImpl.hasFeature("Blah Blah", ""); + assertFalse("domimplementationhasfeature02", success); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMTestCase.java b/xml/src/test/java/tests/org/w3c/dom/DOMTestCase.java new file mode 100644 index 0000000..041b67b --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DOMTestCase.java @@ -0,0 +1,230 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargetClass; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.xml.parsers.DocumentBuilder; + +import org.w3c.dom.Document; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import junit.framework.TestCase; + +@TestTargetClass(Document.class) +public class DOMTestCase extends TestCase { + + public Document load(String docURI, DocumentBuilder builder) { + Document doc = load(resolveURI(docURI), builder); + return doc; + } + + public Document load(URL url, DocumentBuilder builder) { + Document doc = null; + Exception parseException = null; + try { + LoadErrorHandler errorHandler = new LoadErrorHandler(); + builder.setErrorHandler(errorHandler); + doc = builder.parse(url.openStream()); + parseException = errorHandler.getFirstException(); + } catch (Exception ex) { + parseException = ex; + } + builder.setErrorHandler(null); + if (parseException != null) { + // fail("Unexpected exception " + parseException.getMessage()); + throw new RuntimeException("Unexpected exception " + parseException.getMessage(), parseException); + } + return doc; + } + + public void preload(String contentType, String docURI, + boolean willBeModified) { + if ("text/html".equals(contentType) + || "application/xhtml+xml".equals(contentType)) { + if (docURI.startsWith("staff") + || docURI.equals("datatype_normalization")) { + + } + } + } + + private URL resolveURI(String baseURI) { + String docURI = baseURI + ".xml"; + + URL resolvedURI = null; + try { + resolvedURI = new URL(docURI); + if (resolvedURI.getProtocol() != null) { + return resolvedURI; + } + } catch (MalformedURLException ex) { + // fail("Unexpected exception " + ex.getMessage()); + } + // + // build a URL for a test file in the JAR + // + resolvedURI = getClass().getResource("/" + docURI); + if (resolvedURI == null) { + // + // see if it is an absolute URI + // + int firstSlash = docURI.indexOf('/'); + try { + if (firstSlash == 0 + || (firstSlash >= 1 && docURI.charAt(firstSlash - 1) == ':')) { + resolvedURI = new URL(docURI); + } else { + // + // try the files/level?/spec directory + // + String filename = getClass().getPackage().getName(); + filename = "tests/" + + filename.substring(14).replace('.', '/') + + "/files/" + docURI; + resolvedURI = new java.io.File(filename).toURL(); + } + } catch (MalformedURLException ex) { + fail("Unexpected exception " + ex.getMessage()); + } + } + + if (resolvedURI == null) { + fail("resolvedURI is null "); + } + return resolvedURI; + } + + + public String getContentType() { + return "xml"; + } + + public void assertURIEquals(String assertID, String scheme, String path, + String host, String file, String name, String query, + String fragment, Boolean isAbsolute, String actual) { + // + // URI must be non-null + assertNotNull(assertID, actual); + + String uri = actual; + + int lastPound = actual.lastIndexOf("#"); + String actualFragment = ""; + if (lastPound != -1) { + // + // substring before pound + // + uri = actual.substring(0, lastPound); + actualFragment = actual.substring(lastPound + 1); + } + if (fragment != null) { + assertEquals(assertID, fragment, actualFragment); + + } + int lastQuestion = uri.lastIndexOf("?"); + String actualQuery = ""; + if (lastQuestion != -1) { + // + // substring before pound + // + uri = actual.substring(0, lastQuestion); + actualQuery = actual.substring(lastQuestion + 1); + } + if (query != null) { + assertEquals(assertID, query, actualQuery); + + } + int firstColon = uri.indexOf(":"); + int firstSlash = uri.indexOf("/"); + String actualPath = uri; + String actualScheme = ""; + if (firstColon != -1 && firstColon < firstSlash) { + actualScheme = uri.substring(0, firstColon); + actualPath = uri.substring(firstColon + 1); + } + + if (scheme != null) { + assertEquals(assertID, scheme, actualScheme); + } + + if (path != null) { + assertEquals(assertID, path, actualPath); + } + + if (host != null) { + String actualHost = ""; + if (actualPath.startsWith("//")) { + int termSlash = actualPath.indexOf("/", 2); + actualHost = actualPath.substring(0, termSlash); + } + assertEquals(assertID, host, actualHost); + } + + String actualFile = actualPath; + if (file != null || name != null) { + int finalSlash = actualPath.lastIndexOf("/"); + if (finalSlash != -1) { + actualFile = actualPath.substring(finalSlash + 1); + } + if (file != null) { + assertEquals(assertID, file, actualFile); + } + } + + if (name != null) { + String actualName = actualFile; + int finalPeriod = actualFile.lastIndexOf("."); + if (finalPeriod != -1) { + actualName = actualFile.substring(0, finalPeriod); + } + assertEquals(assertID, name, actualName); + } + + if (isAbsolute != null) { + // + // Jar URL's will have any actual path like file:/c:/somedrive... + assertEquals(assertID, isAbsolute.booleanValue(), actualPath + .startsWith("/") + || actualPath.startsWith("file:/")); + } + } + + + private class LoadErrorHandler implements org.xml.sax.ErrorHandler { + private SAXException parseException; + + private int errorCount; + + private int warningCount; + + public LoadErrorHandler() { + parseException = null; + errorCount = 0; + warningCount = 0; + } + + public void error(SAXParseException ex) { + errorCount++; + if (parseException == null) { + parseException = ex; + } + } + + public void warning(SAXParseException ex) { + warningCount++; + } + + public void fatalError(SAXParseException ex) { + if (parseException == null) { + parseException = ex; + } + } + + public SAXException getFirstException() { + return parseException; + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSetting.java b/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSetting.java new file mode 100644 index 0000000..bbb7190 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSetting.java @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2001-2004 World Wide Web Consortium, (Massachusetts Institute + * of Technology, Institut National de Recherche en Informatique et en + * Automatique, Keio University). All Rights Reserved. This program is + * distributed under the W3C's Software Intellectual Property License. This + * program 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 W3C License + * http://www.w3.org/Consortium/Legal/ for more details. + */ + +package tests.org.w3c.dom; + +import javax.xml.parsers.DocumentBuilderFactory; + +/** + * This class is an parser setting, such as non-validating or entity-expanding. + * + * @author Curt Arnold @date 2 Feb 2002 + */ +public final class DocumentBuilderSetting { + /** + * property name. + */ + private final String property; + + /** + * property value. + */ + private final boolean value; + + /** + * strategy used to set or get property value. + */ + private final DocumentBuilderSettingStrategy strategy; + + /** + * coalescing = true. + */ + public static final DocumentBuilderSetting coalescing = + new DocumentBuilderSetting( + "coalescing", + true, + DocumentBuilderSettingStrategy.coalescing); + + /** + * coalescing = false. + */ + public static final DocumentBuilderSetting notCoalescing = + new DocumentBuilderSetting( + "coalescing", + false, + DocumentBuilderSettingStrategy.coalescing); + + /** + * expandEntityReferences = false. + */ + public static final DocumentBuilderSetting expandEntityReferences = + new DocumentBuilderSetting( + "expandEntityReferences", + true, + DocumentBuilderSettingStrategy.expandEntityReferences); + + /** + * expandEntityReferences = true. + */ + public static final DocumentBuilderSetting notExpandEntityReferences = + new DocumentBuilderSetting( + "expandEntityReferences", + false, + DocumentBuilderSettingStrategy.expandEntityReferences); + + /** + * ignoringElementContentWhitespace = true. + */ + public static final DocumentBuilderSetting ignoringElementContentWhitespace = + new DocumentBuilderSetting( + "ignoringElementContentWhitespace", + true, + DocumentBuilderSettingStrategy.ignoringElementContentWhitespace); + + /** + * ignoringElementContentWhitespace = false. + */ + public static final DocumentBuilderSetting + notIgnoringElementContentWhitespace = + new DocumentBuilderSetting( + "ignoringElementContentWhitespace", + false, + DocumentBuilderSettingStrategy.ignoringElementContentWhitespace); + + /** + * namespaceAware = true. + */ + public static final DocumentBuilderSetting namespaceAware = + new DocumentBuilderSetting( + "namespaceAware", + true, + DocumentBuilderSettingStrategy.namespaceAware); + + /** + * namespaceAware = false. + */ + public static final DocumentBuilderSetting notNamespaceAware = + new DocumentBuilderSetting( + "namespaceAware", + false, + DocumentBuilderSettingStrategy.namespaceAware); + + /** + * validating = true. + */ + public static final DocumentBuilderSetting validating = + new DocumentBuilderSetting( + "validating", + true, + DocumentBuilderSettingStrategy.validating); + + /** + * validating = false. + */ + public static final DocumentBuilderSetting notValidating = + new DocumentBuilderSetting( + "validating", + false, + DocumentBuilderSettingStrategy.validating); + + /** + * signed = true. + */ + public static final DocumentBuilderSetting signed = + new DocumentBuilderSetting( + "signed", + true, + DocumentBuilderSettingStrategy.signed); + + /** + * signed = false. + */ + public static final DocumentBuilderSetting notSigned = + new DocumentBuilderSetting( + "signed", + false, + DocumentBuilderSettingStrategy.signed); + + /** + * hasNullString = true. + */ + public static final DocumentBuilderSetting hasNullString = + new DocumentBuilderSetting( + "hasNullString", + true, + DocumentBuilderSettingStrategy.hasNullString); + + /** + * hasNullString = false. + */ + public static final DocumentBuilderSetting notHasNullString = + new DocumentBuilderSetting( + "hasNullString", + false, + DocumentBuilderSettingStrategy.hasNullString); + + /** + * Schema validating enabled. + */ + public static final DocumentBuilderSetting schemaValidating = + new DocumentBuilderSetting( + "schemaValidating", + true, + DocumentBuilderSettingStrategy.schemaValidating); + + /** + * Schema validating disabled. + */ + public static final DocumentBuilderSetting notSchemaValidating = + new DocumentBuilderSetting( + "schemaValidating", + false, + DocumentBuilderSettingStrategy.schemaValidating); + + /** + * Comments ignored. + */ + public static final DocumentBuilderSetting ignoringComments = + new DocumentBuilderSetting( + "ignoringComments", + true, + DocumentBuilderSettingStrategy.ignoringComments); + + /** + * Comments preserved. + */ + public static final DocumentBuilderSetting notIgnoringComments = + new DocumentBuilderSetting( + "ignoringComments", + false, + DocumentBuilderSettingStrategy.ignoringComments); + + /** + * Protected constructor, use static members for supported settings. + * @param property property name, follows JAXP. + * @param value property value + * @param strategy strategy, may not be null + */ + protected DocumentBuilderSetting( + String property, + boolean value, + DocumentBuilderSettingStrategy strategy) { + if (property == null) { + throw new NullPointerException("property"); + } + this.property = property; + this.value = value; + this.strategy = strategy; + } + + /** + * Returns true if the settings have a conflict or are identical. + * + * @param other + * other setting, may not be null. + * @return true if this setting and the specified setting conflict + */ + public final boolean hasConflict(DocumentBuilderSetting other) { + if (other == null) { + throw new NullPointerException("other"); + } + if (other == this) { + return true; + } + return strategy.hasConflict(other.strategy); + } + + /** + * Determines current value of setting. + * @param factory DOMTestDocumentBuilderFactory factory + * @return boolean true if property enabled. + */ + public final boolean hasSetting(DOMDocumentBuilderFactory factory) { + return strategy.hasSetting(factory) == value; + } + + /** + * Attempts to change builder to have this setting. + * @param factory DocumentBuilderFactory Factory for DOM builders + * @throws DOMTestIncompatibleException + * if factory does not support the setting + */ + public final void applySetting(DocumentBuilderFactory factory) { + strategy.applySetting(factory, value); + } + + /** + * Gets the property name. + * @return property name + */ + public final String getProperty() { + return property; + } + + /** + * Gets the property value. + * @return property value + */ + public final boolean getValue() { + return value; + } + + /** + * Gets a string representation of the setting. + * @return string representation + */ + public final String toString() { + StringBuffer builder = new StringBuffer(property); + builder.append('='); + builder.append(String.valueOf(value)); + return builder.toString(); + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSettingStrategy.java b/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSettingStrategy.java new file mode 100644 index 0000000..77bbce8 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSettingStrategy.java @@ -0,0 +1,158 @@ +package tests.org.w3c.dom; + +import java.lang.reflect.Method; + +import javax.xml.parsers.DocumentBuilderFactory; + +public abstract class DocumentBuilderSettingStrategy { + protected DocumentBuilderSettingStrategy() { + } + + private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; + + private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; + + public boolean hasConflict(DocumentBuilderSettingStrategy other) { + return (other == this); + } + + public abstract void applySetting(DocumentBuilderFactory factory, + boolean value); + + public abstract boolean hasSetting(DOMDocumentBuilderFactory factory); + + public static final DocumentBuilderSettingStrategy coalescing = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, + boolean value) { + factory.setCoalescing(value); + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + return factory.isCoalescing(); + } + + }; + + public static final DocumentBuilderSettingStrategy expandEntityReferences = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, boolean value) { + factory.setExpandEntityReferences(value); + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + return factory.isExpandEntityReferences(); + } + }; + + public static final DocumentBuilderSettingStrategy ignoringElementContentWhitespace = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, boolean value) { + factory.setIgnoringElementContentWhitespace(value); + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + return factory.isIgnoringElementContentWhitespace(); + } + }; + + public static final DocumentBuilderSettingStrategy ignoringComments = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, boolean value) { + if (value) { + System.out.println("ignoreComments=true not supported"); + } + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + return false; + } + }; + + public static final DocumentBuilderSettingStrategy namespaceAware = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, boolean value) + { + factory.setNamespaceAware(value); + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + return factory.isNamespaceAware(); + } + }; + + public static final DocumentBuilderSettingStrategy validating = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, boolean value) + { + factory.setValidating(value); + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + return factory.isValidating(); + } + }; + + public static final DocumentBuilderSettingStrategy signed = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, boolean value) + { + if (!value) { + System.out.println("DocumentBuilderSetting.notSigned"); + } + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + return true; + } + }; + + public static final DocumentBuilderSettingStrategy hasNullString = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, boolean value) + { + if (!value) { + System.out.println("DocumentBuilderSetting.notHasNullString"); + } + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + return true; + } + }; + + public static final DocumentBuilderSettingStrategy schemaValidating = new DocumentBuilderSettingStrategy() { + public void applySetting(DocumentBuilderFactory factory, boolean value) + { + if (value) { + factory.setNamespaceAware(true); + factory.setValidating(true); + factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); + } else { + factory.setAttribute(JAXP_SCHEMA_LANGUAGE, + "http://www.w3.org/TR/REC-xml"); + } + } + + public boolean hasSetting(DOMDocumentBuilderFactory factory) { + try { + if (factory.isValidating()) { + Method getAttrMethod = factory.getClass().getMethod( + "getAttribute", new Class[] { String.class }); + String val = (String) getAttrMethod.invoke(factory, + new Object[] { JAXP_SCHEMA_LANGUAGE }); + return W3C_XML_SCHEMA.equals(val); + } + } catch (Exception ex) { + } + return false; + } + + // + // schema validating conflicts with namespaceAware + // and validating + // + public boolean hasConflict(DocumentBuilderSettingStrategy other) { + if (other == this + || other == DocumentBuilderSettingStrategy.namespaceAware + || other == DocumentBuilderSettingStrategy.validating) { + return true; + } + return false; + } + + }; + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentCreateAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/DocumentCreateAttributeNS.java new file mode 100644 index 0000000..e46f3b3 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentCreateAttributeNS.java @@ -0,0 +1,313 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMImplementation; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method createAttributeNS creates an attribute of the given qualified name + * and namespace URI + * + * Invoke the createAttributeNS method on this Document object with a null + * namespaceURI, and a qualifiedName without a prefix. This should return a + * valid Attr node object. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrAttrNS</a> + */ +@TestTargetClass(Document.class) +public final class DocumentCreateAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS1() throws Throwable { + Document doc; + Attr attribute; + String namespaceURI = null; + + String qualifiedName = "test"; + + String nodeName; + + doc = (Document) load("staffNS", builder); + attribute = doc.createAttributeNS(namespaceURI, qualifiedName); + nodeName = attribute.getNodeName(); + + assertEquals("documentcreateattributeNS01", "test", nodeName); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS2() throws Throwable { + Document doc; + Attr attribute1; + Attr attribute2; + String name; + String nodeName; + String nodeValue; + String prefix; + String namespaceURI; + doc = (Document) load("staffNS", builder); + attribute1 = doc.createAttributeNS( + "http://www.w3.org/XML/1998/namespace", "xml:xml"); + name = attribute1.getName(); + nodeName = attribute1.getNodeName(); + nodeValue = attribute1.getNodeValue(); + prefix = attribute1.getPrefix(); + namespaceURI = attribute1.getNamespaceURI(); + assertEquals("documentcreateattributeNS02_att1_name", "xml:xml", name); + assertEquals("documentcreateattributeNS02_att1_nodeName", "xml:xml", + nodeName); + assertEquals("documentcreateattributeNS02_att1_nodeValue", "", + nodeValue); + assertEquals("documentcreateattributeNS02_att1_prefix", "xml", prefix); + assertEquals("documentcreateattributeNS02_att1_namespaceURI", + "http://www.w3.org/XML/1998/namespace", namespaceURI); + attribute2 = doc.createAttributeNS("http://www.w3.org/2000/xmlns/", + "xmlns"); + name = attribute2.getName(); + nodeName = attribute2.getNodeName(); + nodeValue = attribute2.getNodeValue(); + prefix = attribute2.getPrefix(); + namespaceURI = attribute2.getNamespaceURI(); + assertEquals("documentcreateattributeNS02_att2_name", "xmlns", name); + assertEquals("documentcreateattributeNS02_att2_nodeName", "xmlns", + nodeName); + assertEquals("documentcreateattributeNS02_att2_nodeValue", "", + nodeValue); + assertEquals("documentcreateattributeNS02_att2_namespaceURI", + "http://www.w3.org/2000/xmlns/", namespaceURI); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createAttributeNS throws DOMException with INVALID_CHARACTER_ERR code.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS3() throws Throwable { + Document doc; + + String namespaceURI = "http://www.w3.org/DOM/Test/Level2"; + String qualifiedName; + List<String> qualifiedNames = new ArrayList<String>(); + qualifiedNames.add("/"); + qualifiedNames.add("//"); + qualifiedNames.add("\\"); + qualifiedNames.add(";"); + qualifiedNames.add("&"); + qualifiedNames.add("*"); + qualifiedNames.add("]]"); + qualifiedNames.add(">"); + qualifiedNames.add("<"); + + doc = (Document) load("staffNS", builder); + for (int indexN1005A = 0; indexN1005A < qualifiedNames.size(); indexN1005A++) { + qualifiedName = (String) qualifiedNames.get(indexN1005A); + + { + boolean success = false; + try { + doc.createAttributeNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("documentcreateattributeNS03", success); + } + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createAttributeNS throws DOMException with NAMESPACE_ERR code.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS4() throws Throwable { + Document doc; + + String namespaceURI = "http://www.w3.org/DOM/Test/Level2"; + String qualifiedName; + List<String> qualifiedNames = new ArrayList<String>(); + qualifiedNames.add("_:"); + qualifiedNames.add(":0a"); + qualifiedNames.add(":"); + qualifiedNames.add("a:b:c"); + qualifiedNames.add("_::a"); + + doc = (Document) load("staffNS", builder); + for (int indexN1004E = 0; indexN1004E < qualifiedNames.size(); indexN1004E++) { + qualifiedName = (String) qualifiedNames.get(indexN1004E); + + { + boolean success = false; + try { + doc.createAttributeNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("documentcreateattributeNS04", success); + } + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createAttributeNS throws DOMException with NAMESPACE_ERR code.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS5() throws Throwable { + Document doc; + Document newDoc; + DocumentType docType = null; + + DOMImplementation domImpl; + + String namespaceURI = null; + + String qualifiedName = "abc:def"; + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", + "dom:doc", docType); + + { + boolean success = false; + try { + newDoc.createAttributeNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("documentcreateattributeNS05", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createAttributeNS throws DOMException with NAMESPACE_ERR code.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS6() throws Throwable { + Document doc; + Document newDoc; + DocumentType docType = null; + + DOMImplementation domImpl; + + String namespaceURI = "http://www.w3.org/XML/1998 /namespace"; + String qualifiedName = "xml:root"; + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", + "dom:doc", docType); + + { + boolean success = false; + try { + newDoc.createAttributeNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("documentcreateattributeNS06", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createAttributeNS throws DOMException with NAMESPACE_ERR code.", + method = "createAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateAttributeNS7() throws Throwable { + Document doc; + + String namespaceURI = "http://www.W3.org/2000/xmlns"; + String qualifiedName = "xmlns"; + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createAttributeNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("documentcreateattributeNS07", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentCreateElementNS.java b/xml/src/test/java/tests/org/w3c/dom/DocumentCreateElementNS.java new file mode 100644 index 0000000..85f2fff --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentCreateElementNS.java @@ -0,0 +1,169 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.DOMException; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMImplementation; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method createElementNS creates an element of the given valid + * qualifiedName and NamespaceURI. + * + * Invoke the createElementNS method on this Document object with a valid + * namespaceURI and qualifiedName. Check if a valid Element object is returned + * with the same node attributes. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrElNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrElNS</a> + */ +@TestTargetClass(Document.class) +public final class DocumentCreateElementNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS1() throws Throwable { + Document doc; + Element element; + String namespaceURI = "http://www.w3.org/DOM/Test/level2"; + String qualifiedName = "XML:XML"; + String nodeName; + String nsURI; + String localName; + String prefix; + String tagName; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS(namespaceURI, qualifiedName); + nodeName = element.getNodeName(); + nsURI = element.getNamespaceURI(); + localName = element.getLocalName(); + prefix = element.getPrefix(); + tagName = element.getTagName(); + assertEquals("documentcreateelementNS01_nodeName", "XML:XML", nodeName); + assertEquals("documentcreateelementNS01_namespaceURI", + "http://www.w3.org/DOM/Test/level2", nsURI); + assertEquals("documentcreateelementNS01_localName", "XML", localName); + assertEquals("documentcreateelementNS01_prefix", "XML", prefix); + assertEquals("documentcreateelementNS01_tagName", "XML:XML", tagName); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createElementNS throws DOMException with INVALID_CHARACTER_ERR code.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS2() throws Throwable { + Document doc; + + String namespaceURI = null; + + String qualifiedName = "^^"; + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createElementNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("documentcreateelementNS02", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createElementNS throws DOMException with NAMESPACE_ERR code.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS5() throws Throwable { + Document doc; + + String namespaceURI = null; + + String qualifiedName = "null:xml"; + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.createElementNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("documentcreateelementNS05", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that createElementNS throws DOMException with NAMESPACE_ERR code.", + method = "createElementNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testCreateElementNS6() throws Throwable { + Document doc; + Document newDoc; + DocumentType docType = null; + + DOMImplementation domImpl; + + String namespaceURI = "http://www.w3.org/xml/1998/namespace "; + String qualifiedName = "xml:root"; + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", + "dom:doc", docType); + + { + boolean success = false; + try { + newDoc.createElementNS(namespaceURI, qualifiedName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("documentcreateelementNS06", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentGetElementsByTagnameNS.java b/xml/src/test/java/tests/org/w3c/dom/DocumentGetElementsByTagnameNS.java new file mode 100644 index 0000000..390bf11 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentGetElementsByTagnameNS.java @@ -0,0 +1,150 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getElementsByTagNameNS returns a NodeList of all the Elements with + * a given local name and namespace URI in the order in which they are + * encountered in a preorder traversal of the Document tree. + * + * Invoke the getElementsByTagNameNS method on a new Document object with the + * values of namespaceURI=* and localName=*. This should return a nodeList of 1 + * item. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS</a> + * @see <a + * href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a> + */ +@TestTargetClass(Document.class) +public final class DocumentGetElementsByTagnameNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies '*' as parameters.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS1() throws Throwable { + Document doc; + Document newDoc; + DocumentType docType = null; + + DOMImplementation domImpl; + NodeList childList; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + newDoc = domImpl.createDocument(nullNS, "root", docType); + childList = newDoc.getElementsByTagNameNS("*", "*"); + assertEquals("documentgetelementsbytagnameNS01", 1, childList + .getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies '*' as the first parameter.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS2() throws Throwable { + Document doc; + Element docElem; + Element element; + NodeList childList; + + doc = (Document) load("staffNS", builder); + docElem = doc.getDocumentElement(); + element = doc.createElementNS("test", "employeeId"); + docElem.appendChild(element); + childList = doc.getElementsByTagNameNS("*", "employeeId"); + assertEquals("documentgetelementsbytagnameNS02", 6, childList + .getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies wrong namespaceURI as a parameter.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS3() throws Throwable { + Document doc; + NodeList childList; + doc = (Document) load("staffNS", builder); + childList = doc.getElementsByTagNameNS("**", "*"); + assertEquals("documentgetelementsbytagnameNS03", 0, childList + .getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS4() throws Throwable { + Document doc; + NodeList childList; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + childList = doc.getElementsByTagNameNS(nullNS, "0"); + assertEquals("documentgetelementsbytagnameNS04", 0, childList + .getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS5() throws Throwable { + Document doc; + NodeList childList; + doc = (Document) load("staffNS", builder); + childList = doc.getElementsByTagNameNS("null", "elementId"); + assertEquals("documentgetelementsbytagnameNS05", 0, childList + .getLength()); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentGeteEementById.java b/xml/src/test/java/tests/org/w3c/dom/DocumentGeteEementById.java new file mode 100644 index 0000000..7c82ac7 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentGeteEementById.java @@ -0,0 +1,72 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getElementById returns the element whose ID is given by elementId. + * If not such element exists, returns null. + * + * Invoke the getElementById method on this Document object with an invalid + * elementId. This should return a null element. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBId</a> + */ +@TestTargetClass(Document.class) +public final class DocumentGeteEementById extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify getElementById method for existent element.", + method = "getElementById", + args = {java.lang.String.class} + ) + public void testGetElementById() throws Throwable { + Document doc; + Element element; + String elementId = "---"; + doc = (Document) load("staffNS", builder); + element = doc.getElementById(elementId); + assertNull("documentgetelementbyid01", element); + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentImportNode.java b/xml/src/test/java/tests/org/w3c/dom/DocumentImportNode.java new file mode 100644 index 0000000..426a0ad --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentImportNode.java @@ -0,0 +1,699 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.Attr; +import org.w3c.dom.NodeList; +import org.w3c.dom.DOMException; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.ProcessingInstruction; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The importNode method imports a node from another document to this document. + * The returned node has no parent; (parentNode is null). The source node is not + * altered or removed from the original document but a new copy of the source + * node is created. + * + * Using the method importNode with deep=true, import the attribute, "street" of + * the second element node, from a list of nodes whose local names are "address" + * and namespaceURI "http://www.nist.gov" into the same document. Check the + * parentNode, nodeName, nodeType and nodeValue of the imported node to verify + * if it has been imported correctly. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#Core-Document-importNode">http://www.w3.org/TR/DOM-Level-2-Core/core#Core-Document-importNode</a> + */ +@TestTargetClass(Document.class) +public final class DocumentImportNode extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testImportNode1() throws Throwable { +// Document doc; +// Element element; +// Attr attr; +// NodeList childList; +// Node importedAttr; +// String nodeName; +// int nodeType; +// String nodeValue; +// doc = (Document) load("staffNS", builder); +// childList = doc +// .getElementsByTagNameNS("http://www.nist.gov", "address"); +// element = (Element) childList.item(1); +// attr = element.getAttributeNode("street"); +// importedAttr = doc.importNode(attr, false); +// nodeName = importedAttr.getNodeName(); +// nodeValue = importedAttr.getNodeValue(); +// nodeType = (int) importedAttr.getNodeType(); +// assertEquals("documentimportnode01_nodeName", "street", nodeName); +// assertEquals("documentimportnode01_nodeType", 2, nodeType); +// assertEquals("documentimportnode01_nodeValue", "Yes", nodeValue); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException exception.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode2() throws Throwable { + Document doc; + Document docImported; + Element element; + Attr attr; + Node importedAttr; + String nodeName; + int nodeType; + String nodeValue; + NodeList addresses; + Node attrsParent; + doc = (Document) load("staffNS", builder); + docImported = (Document) load("staff", builder); + addresses = doc + .getElementsByTagNameNS("http://www.nist.gov", "address"); + element = (Element) addresses.item(1); + attr = element.getAttributeNodeNS("http://www.nist.gov", "zone"); + importedAttr = docImported.importNode(attr, false); + nodeName = importedAttr.getNodeName(); + nodeType = (int) importedAttr.getNodeType(); + nodeValue = importedAttr.getNodeValue(); + attrsParent = importedAttr.getParentNode(); + assertNull("documentimportnode02_parentNull", attrsParent); + assertEquals("documentimportnode02_nodeName", "emp:zone", nodeName); + assertEquals("documentimportnode02_nodeType", 2, nodeType); + assertEquals("documentimportnode02_nodeValue", "CANADA", nodeValue); + } + +// Assumes validation. +// public void testImportNode3() throws Throwable { +// Document doc; +// Element element; +// Attr attr; +// NodeList childList; +// Node importedAttr; +// String nodeName; +// int nodeType; +// String nodeValue; +// doc = (Document) load("staffNS", builder); +// childList = doc.getElementsByTagNameNS("http://www.nist.gov", +// "employee"); +// element = (Element) childList.item(1); +// attr = element.getAttributeNode("defaultAttr"); +// importedAttr = doc.importNode(attr, false); +// nodeName = importedAttr.getNodeName(); +// nodeValue = importedAttr.getNodeValue(); +// nodeType = (int) importedAttr.getNodeType(); +// assertEquals("documentimportnode03_nodeName", "defaultAttr", nodeName); +// assertEquals("documentimportnode03_nodeType", 2, nodeType); +// assertEquals("documentimportnode03_nodeValue", "defaultVal", nodeValue); +// } + +// Assumes validation. +// public void testImportNode4() throws Throwable { +// Document doc; +// Document newDoc; +// DocumentType docType = null; +// +// DOMImplementation domImpl; +// Element element; +// Attr attr; +// NodeList childList; +// Node importedAttr; +// String nodeName; +// int nodeType; +// String nodeValue; +// doc = (Document) load("staffNS", builder); +// domImpl = doc.getImplementation(); +// newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", +// "l2:root", docType); +// childList = doc.getElementsByTagNameNS("http://www.nist.gov", +// "employee"); +// element = (Element) childList.item(1); +// attr = element.getAttributeNode("defaultAttr"); +// importedAttr = newDoc.importNode(attr, true); +// nodeName = importedAttr.getNodeName(); +// nodeValue = importedAttr.getNodeValue(); +// nodeType = (int) importedAttr.getNodeType(); +// assertEquals("documentimportnode04_nodeName", "defaultAttr", nodeName); +// assertEquals("documentimportnode04_nodeType", 2, nodeType); +// assertEquals("documentimportnode04_nodeValue", "defaultVal", nodeValue); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException exception.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode5() throws Throwable { + Document doc; + Document docImported; + Attr attr; + Node importedAttr; + String nodeName; + int nodeType; + String nodeValue; + String namespaceURI; + doc = (Document) load("staffNS", builder); + docImported = (Document) load("staff", builder); + attr = doc.createAttributeNS("http://www.w3.org/DOM/Test", "a_:b0"); + importedAttr = docImported.importNode(attr, false); + nodeName = importedAttr.getNodeName(); + nodeValue = importedAttr.getNodeValue(); + nodeType = (int) importedAttr.getNodeType(); + namespaceURI = importedAttr.getNamespaceURI(); + assertEquals("documentimportnode05_nodeName", "a_:b0", nodeName); + assertEquals("documentimportnode05_nodeType", 2, nodeType); + assertEquals("documentimportnode05_nodeValue", "", nodeValue); + assertEquals("documentimportnode05_namespaceURI", + "http://www.w3.org/DOM/Test", namespaceURI); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode6() throws Throwable { + Document doc; + + doc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.importNode(doc, false); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_SUPPORTED_ERR); + } + assertTrue("throw_NOT_SUPPORTED_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode7() throws Throwable { + Document doc; + + DocumentType docType; + doc = (Document) load("staffNS", builder); + docType = doc.getDoctype(); + + { + boolean success = false; + try { + doc.importNode(docType, true); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_SUPPORTED_ERR); + } + assertTrue("throw_NOT_SUPPORTED_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode8() throws Throwable { + Document doc; + + DocumentType docType; + DOMImplementation domImpl; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + docType = domImpl.createDocumentType("test:root", nullNS, nullNS); + + { + boolean success = false; + try { + doc.importNode(docType, true); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_SUPPORTED_ERR); + } + assertTrue("throw_NOT_SUPPORTED_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException exception.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode9() throws Throwable { + Document doc; + DocumentFragment docFragment; + NodeList childList; + boolean success; + Node addressNode; + + Node importedDocFrag; + doc = (Document) load("staffNS", builder); + docFragment = doc.createDocumentFragment(); + childList = doc.getElementsByTagNameNS("*", "address"); + addressNode = childList.item(0); + docFragment.appendChild(addressNode); + importedDocFrag = doc.importNode(docFragment, false); + success = importedDocFrag.hasChildNodes(); + assertFalse("documentimportnode09", success); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality; doesn't verify DOMException exceptions.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode10() throws Throwable { + Document doc; + DocumentFragment docFragment; + NodeList childList; + boolean success; + Node addressNode; + + Node importedDocFrag; + doc = (Document) load("staffNS", builder); + docFragment = doc.createDocumentFragment(); + childList = doc.getElementsByTagNameNS("*", "address"); + addressNode = childList.item(0); + docFragment.appendChild(addressNode); + importedDocFrag = doc.importNode(docFragment, true); + success = importedDocFrag.hasChildNodes(); + assertTrue("documentimportnode10", success); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException exception.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode11() throws Throwable { + Document doc; + Element docElement; + Node imported; + boolean success; + String nodeNameOrig; + String nodeNameImported; + doc = (Document) load("staffNS", builder); + docElement = doc.getDocumentElement(); + imported = doc.importNode(docElement, false); + success = imported.hasChildNodes(); + assertFalse("documentimportnode11", success); + nodeNameImported = imported.getNodeName(); + nodeNameOrig = docElement.getNodeName(); + assertEquals("documentimportnode11_NodeName", nodeNameImported, + nodeNameOrig); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException exception.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode12() throws Throwable { + Document doc; + NodeList childList; + Node imported; + Node addressElem; + NodeList addressElemChildren; + NodeList importedChildren; + int addressElemLen; + int importedLen; + doc = (Document) load("staffNS", builder); + childList = doc.getElementsByTagNameNS("*", "address"); + addressElem = childList.item(0); + imported = doc.importNode(addressElem, true); + addressElemChildren = addressElem.getChildNodes(); + importedChildren = imported.getChildNodes(); + addressElemLen = (int) addressElemChildren.getLength(); + importedLen = (int) importedChildren.getLength(); + assertEquals("documentimportnode12", importedLen, addressElemLen); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException exception.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode13() throws Throwable { + Document doc; + NodeList childList; + Node imported; + NodeList importedList; + Node employeeElem; + int importedLen; + doc = (Document) load("staffNS", builder); + childList = doc.getElementsByTagNameNS("*", "employee"); + employeeElem = childList.item(0); + imported = doc.importNode(employeeElem, false); + importedList = imported.getChildNodes(); + importedLen = (int) importedList.getLength(); + assertEquals("documentimportnode13", 0, importedLen); + } + +// Assumes validation. +// public void testImportNode14() throws Throwable { +// Document doc; +// Document newDoc; +// DOMImplementation domImpl; +// DocumentType nullDocType = null; +// +// NodeList childList; +// Node imported; +// Node employeeElem; +// Attr attrNode; +// String attrValue; +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// childList = doc.getElementsByTagNameNS("*", "employee"); +// employeeElem = childList.item(3); +// domImpl = builder.getDOMImplementation(); +// newDoc = domImpl.createDocument(nullNS, "staff", nullDocType); +// imported = newDoc.importNode(employeeElem, true); +// attrNode = ((Element) /* Node */imported).getAttributeNodeNS(nullNS, +// "defaultAttr"); +// assertNull("defaultAttrNotImported", attrNode); +// attrValue = ((Element) /* Node */imported).getAttributeNS( +// "http://www.w3.org/2000/xmlns/", "emp"); +// assertEquals("explicitAttrImported", "http://www.nist.gov", attrValue); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies import of TEXT_NODE.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode15() throws Throwable { + Document doc; + + Node textImport; + Node textToImport; + String nodeValue; + doc = (Document) load("staffNS", builder); + + textToImport = doc + .createTextNode("Document.importNode test for a TEXT_NODE"); + textImport = doc.importNode(textToImport, true); + nodeValue = textImport.getNodeValue(); + assertEquals("documentimportnode15", + "Document.importNode test for a TEXT_NODE", nodeValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies import of COMMENT_NODE", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode17() throws Throwable { + Document doc; + + Node commentImport; + Node commentToImport; + String nodeValue; + doc = (Document) load("staffNS", builder); + + commentToImport = doc + .createComment("Document.importNode test for a COMMENT_NODE"); + commentImport = doc.importNode(commentToImport, true); + nodeValue = commentImport.getNodeValue(); + assertEquals("documentimportnode17", + "Document.importNode test for a COMMENT_NODE", nodeValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException exception.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode18() throws Throwable { + Document doc; + + ProcessingInstruction piImport; + ProcessingInstruction piToImport; + String piData; + String piTarget; + doc = (Document) load("staffNS", builder); + + piToImport = doc.createProcessingInstruction("Target", "Data"); + piImport = (ProcessingInstruction) doc.importNode(piToImport, false); + piTarget = piImport.getTarget(); + piData = piImport.getData(); + assertEquals("documentimportnode18_Target", "Target", piTarget); + assertEquals("documentimportnode18_Data", "Data", piData); + } + +// Assumes validation. +// public void testImportNode19() throws Throwable { +// Document doc; +// DocumentType docTypeNull = null; +// +// Document docImp; +// DOMImplementation domImpl; +// DocumentType docType; +// NamedNodeMap nodeMap; +// Entity entity2; +// Entity entity6; +// Entity entityImp2; +// Entity entityImp6; +// String nodeName; +// String systemId; +// String notationName; +// String nodeNameImp; +// String systemIdImp; +// String notationNameImp; +// doc = (Document) load("staffNS", builder); +// domImpl = doc.getImplementation(); +// docType = doc.getDoctype(); +// docImp = domImpl.createDocument("http://www.w3.org/DOM/Test", "a:b", +// docTypeNull); +// nodeMap = docType.getEntities(); +// assertNotNull("entitiesNotNull", nodeMap); +// entity2 = (Entity) nodeMap.getNamedItem("ent2"); +// entity6 = (Entity) nodeMap.getNamedItem("ent6"); +// entityImp2 = (Entity) docImp.importNode(entity2, false); +// entityImp6 = (Entity) docImp.importNode(entity6, true); +// nodeName = entity2.getNodeName(); +// nodeNameImp = entityImp2.getNodeName(); +// assertEquals("documentimportnode19_Ent2NodeName", nodeName, nodeNameImp); +// nodeName = entity6.getNodeName(); +// nodeNameImp = entityImp6.getNodeName(); +// assertEquals("documentimportnode19_Ent6NodeName", nodeName, nodeNameImp); +// systemId = entity2.getSystemId(); +// systemIdImp = entityImp2.getSystemId(); +// assertEquals("documentimportnode19_Ent2SystemId", systemId, systemIdImp); +// systemId = entity6.getSystemId(); +// systemIdImp = entityImp6.getSystemId(); +// assertEquals("documentimportnode19_Ent6SystemId", systemId, systemIdImp); +// notationName = entity2.getNotationName(); +// notationNameImp = entityImp2.getNotationName(); +// assertEquals("documentimportnode19_Ent2NotationName", notationName, +// notationNameImp); +// notationName = entity6.getNotationName(); +// notationNameImp = entityImp6.getNotationName(); +// assertEquals("documentimportnode19_Ent6NotationName", notationName, +// notationNameImp); +// } + +// Assumes validation. +// public void testImportNode20() throws Throwable { +// Document doc; +// Document docImp; +// DOMImplementation domImpl; +// DocumentType docType; +// DocumentType docTypeNull = null; +// +// NamedNodeMap nodeMap; +// Entity entity4; +// Entity entityImp4; +// Element element; +// CharacterData cdata; +// ProcessingInstruction pi; +// NodeList childList; +// NodeList elemchildList; +// String ent4Name; +// String ent4ImpName; +// String cdataVal; +// String piTargetVal; +// String piDataVal; +// doc = (Document) load("staffNS", builder); +// domImpl = doc.getImplementation(); +// docType = doc.getDoctype(); +// docImp = domImpl.createDocument("http://www.w3.org/DOM/Test", "a:b", +// docTypeNull); +// nodeMap = docType.getEntities(); +// entity4 = (Entity) nodeMap.getNamedItem("ent4"); +// entityImp4 = (Entity) docImp.importNode(entity4, true); +// childList = entityImp4.getChildNodes(); +// element = (Element) childList.item(0); +// elemchildList = element.getChildNodes(); +// cdata = (CharacterData) elemchildList.item(0); +// pi = (ProcessingInstruction) childList.item(1); +// ent4Name = entity4.getNodeName(); +// ent4ImpName = entityImp4.getNodeName(); +// cdataVal = cdata.getData(); +// piTargetVal = pi.getTarget(); +// piDataVal = pi.getData(); +// assertEquals("documentimportnode20_Ent4NodeName", ent4Name, ent4ImpName); +// assertEquals("documentimportnode20_Cdata", "Element data", cdataVal); +// assertEquals("documentimportnode20_PITarget", "PItarget", piTargetVal); +// assertEquals("documentimportnode20_PIData", "PIdata", piDataVal); +// } + +// TODO Fails on JDK. Why? +// public void testImportNode21() throws Throwable { +// +// +// Document doc; +// DocumentType docTypeNull = null; +// +// Document docImp; +// DOMImplementation domImpl; +// NodeList addressList; +// NodeList addressChildList; +// Element element; +// EntityReference entRef2; +// EntityReference entRefImp2; +// EntityReference entRef3; +// EntityReference entRefImp3; +// String nodeName2; +// String nodeName3; +// String nodeNameImp2; +// String nodeNameImp3; +// NodeList nodes; +// Node nodeImp3; +// Node nodeImp2; +// String nodeValueImp2; +// String nodeValueImp3; +// doc = (Document) load("staffNS", builder); +// domImpl = doc.getImplementation(); +// docImp = domImpl.createDocument("http://www.w3.org/DOM/Test", "a:b", +// docTypeNull); +// addressList = doc.getElementsByTagName("address"); +// element = (Element) addressList.item(1); +// addressChildList = element.getChildNodes(); +// entRef2 = (EntityReference) addressChildList.item(0); +// entRef3 = (EntityReference) addressChildList.item(2); +// entRefImp2 = (EntityReference) docImp.importNode(entRef2, true); +// entRefImp3 = (EntityReference) docImp.importNode(entRef3, false); +// nodeName2 = entRef2.getNodeName(); +// nodeName3 = entRef3.getNodeName(); +// nodeNameImp2 = entRefImp2.getNodeName(); +// nodeNameImp3 = entRefImp3.getNodeName(); +// assertEquals("documentimportnode21_Ent2NodeName", nodeName2, +// nodeNameImp2); +// assertEquals("documentimportnode21_Ent3NodeName", nodeName3, +// nodeNameImp3); +// entRefImp2 = (EntityReference) doc.importNode(entRef2, true); +// entRefImp3 = (EntityReference) doc.importNode(entRef3, false); +// nodes = entRefImp2.getChildNodes(); +// nodeImp2 = nodes.item(0); +// nodeValueImp2 = nodeImp2.getNodeValue(); +// nodes = entRefImp3.getChildNodes(); +// nodeImp3 = nodes.item(0); +// nodeValueImp3 = nodeImp3.getNodeValue(); +// assertEquals("documentimportnode21_Ent2NodeValue", "1900 Dallas Road", +// nodeValueImp2); +// assertEquals("documentimportnode21_Ent3Nodevalue", "Texas", +// nodeValueImp3); +// +// } + +// Assumes validation. +// public void testImportNode22() throws Throwable { +// Document doc; +// DocumentType docTypeNull = null; +// +// Document docImp; +// DOMImplementation domImpl; +// DocumentType docType; +// NamedNodeMap nodeMap; +// Notation notation1; +// Notation notation2; +// +// String publicId1; +// String publicId1Imp; +// String publicId1NewImp; +// String publicId2Imp; +// +// String systemId1Imp; +// String systemId1NewImp; +// String systemId2; +// String systemId2Imp; +// String systemId2NewImp; +// doc = (Document) load("staffNS", builder); +// domImpl = doc.getImplementation(); +// docType = doc.getDoctype(); +// docImp = domImpl.createDocument("http://www.w3.org/DOM/Test", "a:b", +// docTypeNull); +// nodeMap = docType.getNotations(); +// assertNotNull("notationsNotNull", nodeMap); +// notation1 = (Notation) nodeMap.getNamedItem("notation1"); +// notation2 = (Notation) nodeMap.getNamedItem("notation2"); +// doc.importNode(notation1, true); +// doc.importNode(notation2, false); +// docImp.importNode(notation1, false); +// docImp.importNode(notation2, true); +// publicId1 = notation1.getPublicId(); +// publicId1Imp = notation1.getPublicId(); +// publicId1NewImp = notation1.getPublicId(); +// systemId1Imp = notation1.getSystemId(); +// systemId1NewImp = notation1.getSystemId(); +// publicId2Imp = notation2.getPublicId(); +// notation2.getPublicId(); +// systemId2 = notation2.getSystemId(); +// systemId2Imp = notation2.getSystemId(); +// systemId2NewImp = notation2.getSystemId(); +// assertEquals("documentimportnode22_N1PID", publicId1, publicId1Imp); +// assertEquals("documentimportnode22_N1NPID", publicId1, publicId1NewImp); +// assertNull("documentimportnode22_N1SID", systemId1Imp); +// assertNull("documentimportnode22_N1NSID", systemId1NewImp); +// assertEquals("documentimportnode22_N2SID", systemId2, systemId2Imp); +// assertEquals("documentimportnode22_N2NSID", systemId2, systemId2NewImp); +// assertNull("documentimportnode22_N2PID", publicId2Imp); +// assertNull("documentimportnode22_N2NPID", publicId2Imp); +// } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentTypeInternalSubset.java b/xml/src/test/java/tests/org/w3c/dom/DocumentTypeInternalSubset.java new file mode 100644 index 0000000..9e79788 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentTypeInternalSubset.java @@ -0,0 +1,76 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.DocumentType; +import org.w3c.dom.Document; +import org.w3c.dom.DOMImplementation; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getInternalSubset() returns the internal subset as a string. + * + * Create a new DocumentType node with null values for publicId and systemId. + * Verify that its internal subset is null. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-internalSubset">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-internalSubset</a> + * @see <a + * href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a> + */ +@TestTargetClass(DocumentType.class) +public final class DocumentTypeInternalSubset extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't check positive case.", + method = "getInternalSubset", + args = {} + ) + public void testGetInternalSubset() throws Throwable { + Document doc; + DocumentType docType; + DOMImplementation domImpl; + String internal; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + docType = domImpl.createDocumentType("l2:root", nullNS, nullNS); + internal = docType.getInternalSubset(); + assertNull("internalSubsetNull", internal); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentTypePublicId.java b/xml/src/test/java/tests/org/w3c/dom/DocumentTypePublicId.java new file mode 100644 index 0000000..26e9a5f --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentTypePublicId.java @@ -0,0 +1,97 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001-2003 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMImplementation; + +import javax.xml.parsers.DocumentBuilder; + + + +/** + * The method getInternalSubset() returns the public identifier of the external subset. + * + * Create a new DocumentType node with the value "PUB" for its publicId. + * Check the value of the publicId attribute using getPublicId(). +* @author IBM +* @author Neil Delima +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-publicId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-publicId</a> +* @see <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a> +*/ +@TestTargetClass(DocumentType.class) +public final class DocumentTypePublicId extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getPublicId", + args = {} + ) + public void testGetPublicId() throws Throwable { + Document doc; + DocumentType docType; + DOMImplementation domImpl; + String publicId; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + docType = domImpl.createDocumentType("l2:root", "PUB", nullNS); + publicId = docType.getPublicId(); + assertEquals("documenttypepublicid01", "PUB", publicId); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentTypeSystemId.java b/xml/src/test/java/tests/org/w3c/dom/DocumentTypeSystemId.java new file mode 100644 index 0000000..fcad024 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/DocumentTypeSystemId.java @@ -0,0 +1,95 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.DocumentType; +import org.w3c.dom.Document; +import org.w3c.dom.DOMImplementation; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getInternalSubset() returns the public identifier of the external subset. + * + * Create a new DocumentType node with the value "SYS" for its systemId and PUB for + * its publicId. Check the value of the systemId and pbulicId attributes. +* @author IBM +* @author Neil Delima +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-systemId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-systemId</a> +*/ +@TestTargetClass(DocumentType.class) +public final class DocumentTypeSystemId extends DOMTestCase { + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getSystemId", + args = {} + ) + public void testGetSystemId() throws Throwable { + Document doc; + DocumentType docType; + DOMImplementation domImpl; + String publicId; + String systemId; + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + docType = domImpl.createDocumentType("l2:root", "PUB", "SYS"); + publicId = docType.getPublicId(); + systemId = docType.getSystemId(); + assertEquals("documenttypepublicid01", "PUB", publicId); + assertEquals("documenttypesystemid01", "SYS", systemId); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNS.java new file mode 100644 index 0000000..8505459 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNS.java @@ -0,0 +1,89 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001-2004 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargetClass; + +import javax.xml.parsers.DocumentBuilder; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + + +/** + * The method getAttributeNS retrieves an attribute value by local name and namespace URI. + * Using the getAttributeNodeNS, retreive and verify the value of the default + * attribute node. + * +* @author IBM +* @author Neil Delima +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAttrNS</a> +* @see <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a> +*/ +@TestTargetClass(Element.class) +public final class ElementGetAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testGetAttributeNS() throws Throwable { +// Document doc; +// Element element; +// String attrValue; +// NodeList childList; +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// childList = doc.getElementsByTagNameNS("http://www.nist.gov", +// "employee"); +// element = (Element) childList.item(1); +// attrValue = element.getAttributeNS(nullNS, "defaultAttr"); +// assertEquals("elementgetattributens02", "defaultVal", attrValue); +// } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNodeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNodeNS.java new file mode 100644 index 0000000..7760ba8 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNodeNS.java @@ -0,0 +1,139 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getAttributeNodeNS retrieves an Attr node by local name and + * namespace URI. Create a new element node and add 2 new attribute nodes to it + * that have the same local name but different namespaceURIs and prefixes. + * Retrieve an attribute using namespace and localname and check its value, name + * and namespaceURI. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAtNodeNS</a> + */ +@TestTargetClass(Element.class) +public final class ElementGetAttributeNodeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getAttributeNodeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetAttributeNodeNS1() throws Throwable { + Document doc; + Element element; + Attr attribute1; + Attr attribute2; + + + Attr attribute; + String attrValue; + String attrName; + String attNodeName; + String attrLocalName; + String attrNS; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("namespaceURI", "root"); + attribute1 = doc.createAttributeNS("http://www.w3.org/DOM/Level2", + "l2:att"); + element.setAttributeNodeNS(attribute1); + attribute2 = doc.createAttributeNS("http://www.w3.org/DOM/Level1", + "att"); + element.setAttributeNodeNS(attribute2); + attribute = element.getAttributeNodeNS("http://www.w3.org/DOM/Level2", + "att"); + attrValue = attribute.getNodeValue(); + attrName = attribute.getName(); + attNodeName = attribute.getNodeName(); + attrLocalName = attribute.getLocalName(); + attrNS = attribute.getNamespaceURI(); + assertEquals("elementgetattributenodens01_attrValue", "", attrValue); + assertEquals("elementgetattributenodens01_attrName", "l2:att", attrName); + assertEquals("elementgetattributenodens01_attrNodeName", "l2:att", + attNodeName); + assertEquals("elementgetattributenodens01_attrLocalName", "att", + attrLocalName); + assertEquals("elementgetattributenodens01_attrNs", + "http://www.w3.org/DOM/Level2", attrNS); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getAttributeNodeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetAttributeNodeNS2() throws Throwable { + Document doc; + Element element; + Attr attribute; + + String attrValue; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("namespaceURI", "root"); + attribute = doc.createAttributeNS("http://www.w3.org/DOM/Level2", + "l2:att"); + element.setAttributeNodeNS(attribute); + attribute = element.getAttributeNodeNS("http://www.w3.org/DOM/Level2", + "att"); + attrValue = attribute.getNodeValue(); + assertEquals("elementgetattributenodens02", "", attrValue); + } + +// Assumes validation. +// public void testGetAttributeNodeNS3() throws Throwable { +// Document doc; +// Element element; +// Attr attribute; +// String attrValue; +// NodeList childList; +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// childList = doc.getElementsByTagNameNS("http://www.nist.gov", +// "employee"); +// element = (Element) childList.item(1); +// attribute = element.getAttributeNodeNS(nullNS, "defaultAttr"); +// attrValue = attribute.getNodeValue(); +// assertEquals("elementgetattributenodens03", "defaultVal", attrValue); +// } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementGetElementsByTagNameNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementGetElementsByTagNameNS.java new file mode 100644 index 0000000..f03007a --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ElementGetElementsByTagNameNS.java @@ -0,0 +1,122 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getElementsByTagNameNS returns a NodeList of all the Elements with + * a given local name and namespace URI in the order in which they are + * encountered in a preorder traversal of the Document tree. Invoke + * getElementsByTagNameNS on the documentElement with values for namespaceURI + * '*' and localName '*'. Verify if this returns a nodeList of 0 elements. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS</a> + */ +@TestTargetClass(Element.class) +public final class ElementGetElementsByTagNameNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS1() throws Throwable { + Document doc; + Element element; + NodeList elementList; + doc = (Document) load("staffNS", builder); + element = doc.getDocumentElement(); + elementList = element.getElementsByTagNameNS("**", "*"); + assertEquals("elementgetelementsbytagnamens02", 0, elementList + .getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS4() throws Throwable { + Document doc; + Element element; + Element child1; + Element child2; + Element child3; + + NodeList elementList; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM", "root"); + child1 = doc.createElementNS("http://www.w3.org/DOM/Level1", + "dom:child"); + child2 = doc.createElementNS(nullNS, "child"); + child3 = doc.createElementNS("http://www.w3.org/DOM/Level2", + "dom:child"); + element.appendChild(child1); + element.appendChild(child2); + element.appendChild(child3); + elementList = element.getElementsByTagNameNS(nullNS, "child"); + assertEquals("elementgetelementsbytagnamens04_1", 1, elementList + .getLength()); + elementList = element.getElementsByTagNameNS("*", "child"); + assertEquals("elementgetelementsbytagnamens04_2", 3, elementList + .getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS5() throws Throwable { + Document doc; + Element element; + NodeList elementList; + doc = (Document) load("staffNS", builder); + element = doc.getDocumentElement(); + elementList = element.getElementsByTagNameNS( + "http://www.altavista.com", "*"); + assertEquals("elementgetelementsbytagnamens05", 1, elementList + .getLength()); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementHasAttribute.java b/xml/src/test/java/tests/org/w3c/dom/ElementHasAttribute.java new file mode 100644 index 0000000..711a1ab --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ElementHasAttribute.java @@ -0,0 +1,123 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method hasAttribute returns true when an attribute with a given name is + * specified on this element or has a default value, false otherwise Invoke the + * hasAttribute method to check if the documentElement has attributres. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs</a> + */ +@TestTargetClass(Element.class) +public final class ElementHasAttribute extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies hasAttribute method with empty string as a parameter.", + method = "hasAttribute", + args = {java.lang.String.class} + ) + public void testHasAttribute1() throws Throwable { + Document doc; + Element element; + boolean state; + doc = (Document) load("staff", builder); + element = doc.getDocumentElement(); + state = element.hasAttribute(""); + assertFalse("elementhasattribute01", state); + } + +// Assumes validation. +// public void testHasAttribute2() throws Throwable { +// Document doc; +// Element element; +// boolean state; +// NodeList elementList; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("emp:employee"); +// element = (Element) elementList.item(0); +// assertNotNull("empEmployeeNotNull", element); +// state = element.hasAttribute("defaultAttr"); +// assertTrue("elementhasattribute02", state); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "hasAttribute", + args = {java.lang.String.class} + ) + public void testHasAttribute3() throws Throwable { + Document doc; + Element element; + boolean state; + Attr attribute; + + doc = (Document) load("staff", builder); + element = doc.createElement("address"); + attribute = doc.createAttribute("domestic"); + state = element.hasAttribute("domestic"); + assertFalse("elementhasattribute03_False", state); + element.setAttributeNode(attribute); + state = element.hasAttribute("domestic"); + assertTrue("elementhasattribute03_True", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "hasAttribute", + args = {java.lang.String.class} + ) + public void testHasAttribute4() throws Throwable { + Document doc; + Element element; + boolean state; + Attr attribute; + + doc = (Document) load("staff", builder); + element = doc.createElement("address"); + attribute = doc.createAttribute("domestic"); + element.setAttributeNode(attribute); + state = element.hasAttribute("domestic"); + assertTrue("elementhasattribute04", state); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementHasAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementHasAttributeNS.java new file mode 100644 index 0000000..e0c9fd9 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ElementHasAttributeNS.java @@ -0,0 +1,139 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method hasAttributeNS returns true when an attribute with a given local + * name and namespace URI is specified on this element or has a default value, + * false otherwise. + * + * Retreive the first employee element node. Invoke the hasAttributeNS method to + * check if it has the xmlns attribute that belongs to the namespace + * http://www.w3.org/2000/xmlns/. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttrNS</a> + */ +@TestTargetClass(Element.class) +public final class ElementHasAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "hasAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void _testHasAttributeNS1() throws Throwable { + Document doc; + Element element; + boolean state; + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "employee"); + element = (Element) elementList.item(0); + state = element + .hasAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns"); + assertTrue("elementhasattributens01", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "hasAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasAttributeNS2() throws Throwable { + Document doc; + Element element; + boolean state; + Attr attribute; + + doc = (Document) load("staff", builder); + element = doc.createElementNS("http://www.w3.org/DOM", "address"); + attribute = doc.createAttributeNS("http://www.w3.org/DOM", "domestic"); + element.setAttributeNode(attribute); + state = element.hasAttributeNS("http://www.w3.org/DOM", "domestic"); + assertTrue("hasDomesticAttr", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "hasAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasAttributeNS3() throws Throwable { + Document doc; + Element element; + boolean state; + Attr attribute; + + String nullNS = null; + + doc = (Document) load("staff", builder); + element = doc.createElementNS("http://www.w3.org/DOM", "address"); + assertNotNull("createElementNotNull", element); + attribute = doc.createAttributeNS(nullNS, "domestic"); + element.setAttributeNode(attribute); + state = element.hasAttributeNS(nullNS, "domestic"); + assertTrue("elementhasattributens03", state); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementRemoveAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementRemoveAttributeNS.java new file mode 100644 index 0000000..72c56e9 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ElementRemoveAttributeNS.java @@ -0,0 +1,80 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method removeAttributeNS removes an attribute by local name and namespace + * URI. Create a new element and add a new attribute node to it. Remove the + * attribute node using the removeAttributeNodeNS method. Check if the attribute + * was remove by invoking the hasAttributeNS method on the element and check if + * it returns false. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElRemAtNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElRemAtNS</a> + */ +@TestTargetClass(Element.class) +public final class ElementRemoveAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "removeAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveAttributeNS() throws Throwable { + Document doc; + Element element; + boolean state; + Attr attribute; + + doc = (Document) load("staff", builder); + element = doc.createElementNS("http://www.w3.org/DOM", "elem"); + attribute = doc.createAttributeNS( + "http://www.w3.org/DOM/Test/createAttributeNS", "attr"); + element.setAttributeNodeNS(attribute); + element.removeAttributeNS( + "http://www.w3.org/DOM/Test/createAttributeNS", "attr"); + state = element.hasAttributeNS( + "http://www.w3.org/DOM/Test/createAttributeNS", "attr"); + assertFalse("elementremoveattributens01", state); + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNS.java new file mode 100644 index 0000000..babd6f1 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNS.java @@ -0,0 +1,266 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Element; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.DOMException; +import org.w3c.dom.Node; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method setAttributeNS adds a new attribute. Create a new element and add + * a new attribute node to it using the setAttributeNS method. Check if the + * attribute was correctly set by invoking the getAttributeNodeNS method and + * checking the nodeName and nodeValue of the returned nodes. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAttrNS</a> + */ +@TestTargetClass(Element.class) +public final class ElementSetAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS1() throws Throwable { + Document doc; + Element element; + Attr attribute; + String attrName; + String attrValue; + doc = (Document) load("staff", builder); + element = doc.createElementNS("http://www.w3.org/DOM", "dom:elem"); + element.setAttributeNS("http://www.w3.org/DOM/Test/setAttributeNS", + "attr", "value"); + attribute = element.getAttributeNodeNS( + "http://www.w3.org/DOM/Test/setAttributeNS", "attr"); + attrName = attribute.getNodeName(); + attrValue = attribute.getNodeValue(); + assertEquals("elementsetattributens01_attrName", "attr", attrName); + assertEquals("elementsetattributens01_attrValue", "value", attrValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS2() throws Throwable { + Document doc; + Element element; + Attr attribute; + NodeList elementList; + String attrName; + String attrValue; + doc = (Document) load("staff", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = (Element) elementList.item(0); + element.setAttributeNS("http://www.w3.org/DOM/Test/setAttributeNS", + "this:street", "Silver Street"); + attribute = element.getAttributeNodeNS( + "http://www.w3.org/DOM/Test/setAttributeNS", "street"); + attrName = attribute.getNodeName(); + attrValue = attribute.getNodeValue(); + assertEquals("elementsetattributens02_attrName", "this:street", + attrName); + assertEquals("elementsetattributens02_attrValue", "Silver Street", + attrValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS3() throws Throwable { + Document doc; + Element element; + Attr attribute; + NodeList elementList; + String attrName; + String attrValue; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:employee"); + element = (Element) elementList.item(0); + assertNotNull("empEmployeeNotNull", element); + element.setAttributeNS("http://www.w3.org/DOM/Test/1", "defaultAttr", + "default1"); + element.setAttributeNS("http://www.w3.org/DOM/Test/2", "defaultAttr", + "default2"); + attribute = element.getAttributeNodeNS("http://www.w3.org/DOM/Test/1", + "defaultAttr"); + attrName = attribute.getNodeName(); + attrValue = attribute.getNodeValue(); + assertEquals("elementsetattributens03_attrName", "defaultAttr", + attrName); + assertEquals("elementsetattributens03_attrValue", "default1", attrValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with INVALID_CHARACTER_ERR.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS4() throws Throwable { + Document doc; + Element element; + String qualifiedName; + List<String> qualifiedNames = new ArrayList<String>(); + qualifiedNames.add("/"); + qualifiedNames.add("//"); + qualifiedNames.add("\\"); + qualifiedNames.add(";"); + qualifiedNames.add("&"); + qualifiedNames.add("*"); + qualifiedNames.add("]]"); + qualifiedNames.add(">"); + qualifiedNames.add("<"); + + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test/L2", + "dom:elem"); + for (int indexN10058 = 0; indexN10058 < qualifiedNames.size(); indexN10058++) { + qualifiedName = (String) qualifiedNames.get(indexN10058); + + { + boolean success = false; + try { + element.setAttributeNS("http://www.w3.org/DOM/Test/L2", + qualifiedName, "test"); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("elementsetattributens04", success); + } + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS5() throws Throwable { + Document doc; + Element element; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test/L2", + "dom:elem"); + + { + boolean success = false; + try { + element.setAttributeNS(nullNS, "dom:root", "test"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("elementsetattributens05", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS8() throws Throwable { + Document doc; + Element element; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOMTest/level2", + "dom:elem"); + + { + boolean success = false; + try { + element.setAttributeNS("http://www.w3.org/DOMTest/level2", + "xmlns", "test"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("elementsetattributens08_Err1", success); + } + + { + boolean success = false; + try { + element.setAttributeNS("http://www.w3.org/DOMTest/level2", + "xmlns:root", "test"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("elementsetattributens08_Err2", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNSURINull() throws Throwable { + String namespaceURI = null; + + String qualifiedName = "emp:qualifiedName"; + Document doc; + NodeList elementList; + Node testAddr; + doc = (Document) load("staff", builder); + elementList = doc.getElementsByTagName("employee"); + testAddr = elementList.item(0); + + { + boolean success = false; + try { + ((Element) /*Node */testAddr).setAttributeNS(namespaceURI, qualifiedName, "newValue"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNodeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNodeNS.java new file mode 100644 index 0000000..2a115e0 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNodeNS.java @@ -0,0 +1,276 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.Attr; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; +import org.w3c.dom.DOMException; +import org.w3c.dom.EntityReference; + +import javax.xml.parsers.DocumentBuilder; + +/** + * Testing Element.setAttributeNodeNS: If an attribute with that local name and + * that namespace URI is already present in the element, it is replaced by the + * new one. Create a new element and two new attribute nodes (in the same + * namespace and same localNames). Add the two new attribute nodes to the + * element node using the setAttributeNodeNS method. Check that only one + * attribute is added, check the value of this attribute. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS</a> + */ +@TestTargetClass(Element.class) +public final class ElementSetAttributeNodeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNodeNS1() throws Throwable { + Document doc; + Element element; + Attr attribute1; + Attr attribute2; + Attr attrNode; + String attrName; + String attrNS; + + NamedNodeMap attributes; + + int length; + doc = (Document) load("staff", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test/Level2", + "new:element"); + attribute1 = doc.createAttributeNS("http://www.w3.org/DOM/Test/att1", + "p1:att"); + attribute2 = doc.createAttributeNS("http://www.w3.org/DOM/Test/att1", + "p2:att"); + attribute2.setValue("value2"); + element.setAttributeNodeNS(attribute1); + element.setAttributeNodeNS(attribute2); + attrNode = element.getAttributeNodeNS( + "http://www.w3.org/DOM/Test/att1", "att"); + attrName = attrNode.getNodeName(); + attrNS = attrNode.getNamespaceURI(); + assertEquals("elementsetattributenodens01_attrName", "p2:att", attrName); + assertEquals("elementsetattributenodens01_attrNS", + "http://www.w3.org/DOM/Test/att1", attrNS); + attributes = element.getAttributes(); + length = (int) attributes.getLength(); + assertEquals("length", 1, length); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNodeNS2() throws Throwable { + Document doc; + Element element; + Element element2; + Attr attribute; + Attr attributeCloned; + Attr newAttr; + NodeList elementList; + String attrName; + String attrValue; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "address"); + element = (Element) elementList.item(1); + attribute = element.getAttributeNodeNS(nullNS, "street"); + attributeCloned = (Attr) attribute.cloneNode(true); + element2 = (Element) elementList.item(2); + newAttr = element2.setAttributeNodeNS(attributeCloned); + attrName = newAttr.getNodeName(); + attrValue = newAttr.getNodeValue(); + assertEquals("elementsetattributenodens02_attrName", "street", attrName); + assertEquals("elementsetattributenodens02_attrValue", "Yes", attrValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with INUSE_ATTRIBUTE_ERR code.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNodeNS3() throws Throwable { + Document doc; + Element element1; + Element element2; + Attr attribute; + + NodeList elementList; + String nullNS = null; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "address"); + element1 = (Element) elementList.item(1); + attribute = element1.getAttributeNodeNS(nullNS, "street"); + element2 = (Element) elementList.item(2); + + { + boolean success = false; + try { + element2.setAttributeNodeNS(attribute); + } catch (DOMException ex) { + success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR); + } + assertTrue("elementsetattributenodens03", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with INUSE_ATTRIBUTE_ERR code.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNodeNS4() throws Throwable { + Document doc; + Element element1; + Element element2; + Attr attribute; + + doc = (Document) load("staffNS", builder); + element1 = doc.createElementNS("http://www.w3.org/DOM/Test", "elem1"); + element2 = doc.createElementNS("http://www.w3.org/DOM/Test", "elem2"); + attribute = doc.createAttributeNS("http://www.w3.org/DOM/Test", "attr"); + element1.setAttributeNodeNS(attribute); + + { + boolean success = false; + try { + element2.setAttributeNodeNS(attribute); + } catch (DOMException ex) { + success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR); + } + assertTrue("elementsetattributenodens04", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with WRONG_DOCUMENT_ERR code.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNodeNS5() throws Throwable { + Document doc; + Document docAlt; + Element element; + Attr attribute; + + doc = (Document) load("staffNS", builder); + docAlt = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test", "elem1"); + attribute = docAlt.createAttributeNS("http://www.w3.org/DOM/Test", + "attr"); + + { + boolean success = false; + try { + element.setAttributeNodeNS(attribute); + } catch (DOMException ex) { + success = (ex.code == DOMException.WRONG_DOCUMENT_ERR); + } + assertTrue("throw_WRONG_DOCUMENT_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NO_MODIFICATION_ALLOWED_ERR code.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void _testSetAttributeNodeNS6() throws Throwable { + Document doc; + Element element; + Attr attribute; + Attr attribute2; + EntityReference entRef; + NodeList elementList; + + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test", "elem1"); + attribute = doc.createAttributeNS("http://www.w3.org/DOM/Test", "attr"); + entRef = doc.createEntityReference("ent4"); + attribute.appendChild(entRef); + element.setAttributeNodeNS(attribute); + elementList = entRef.getChildNodes(); + element = (Element) elementList.item(0); + attribute2 = doc.createAttributeNS("http://www.w3.org/DOM/Test", + "attr2"); + + { + boolean success = false; + try { + element.setAttributeNodeNS(attribute2); + } catch (DOMException ex) { + success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); + } + assertTrue("elementsetattributenodens06", success); + } + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/GetAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/GetAttributeNS.java new file mode 100644 index 0000000..ae5936c --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/GetAttributeNS.java @@ -0,0 +1,187 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2003 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getAttributeNS(namespaceURI,localName)" method retrieves an attribute + * value by local name and NamespaceURI. + * + * Retrieve the first "emp:address" element. The value returned by the + * "getAttributeNS()" method should be the value "DISTRICT" since the attribute + * has a default value. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAttrNS</a> + * @see <a + * href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=238">http://www.w3.org/Bugs/Public/show_bug.cgi?id=238</a> + */ +@TestTargetClass(Element.class) +public final class GetAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testGetAttributeNS1() throws Throwable { +// String namespaceURI = "http://www.nist.gov"; +// String localName = "district"; +// +// Document doc; +// NodeList elementList; +// Element testAddr; +// String attrValue; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("emp:address"); +// testAddr = (Element) elementList.item(0); +// attrValue = testAddr.getAttributeNS(namespaceURI, localName); +// assertEquals("attrValue", "DISTRICT", attrValue); +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetAttributeNS2() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String localName = "district"; + String qualifiedName = "emp:district"; + Document doc; + Attr newAttribute; + NodeList elementList; + Element testAddr; + + String attrValue; + doc = (Document) load("staffNS", builder); + newAttribute = doc.createAttributeNS(namespaceURI, qualifiedName); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + testAddr.setAttributeNodeNS(newAttribute); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + attrValue = testAddr.getAttributeNS(namespaceURI, localName); + assertEquals("throw_Equals", "", attrValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetAttributeNS3() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String localName = "domestic"; + Document doc; + NodeList elementList; + Element testAddr; + String attrValue; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + testAddr.removeAttributeNS(namespaceURI, localName); + attrValue = testAddr.getAttributeNS(namespaceURI, localName); + assertEquals("throw_Equals", "", attrValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetAttributeNS4() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String localName = "blank"; + String qualifiedName = "emp:blank"; + Document doc; + + NodeList elementList; + Element testAddr; + + String attrValue; + doc = (Document) load("staffNS", builder); + doc.createAttributeNS(namespaceURI, qualifiedName); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + testAddr.setAttributeNS(namespaceURI, qualifiedName, "NewValue"); + attrValue = testAddr.getAttributeNS(namespaceURI, localName); + assertEquals("throw_Equals", "NewValue", attrValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetAttributeNS5() throws Throwable { + Document doc; + NodeList elementList; + Element testAddr; + String attrValue; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + attrValue = testAddr.getAttributeNS("http://www.nist.gov", "domestic"); + assertEquals("attrValue", "Yes", attrValue); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/GetAttributeNodeNS.java b/xml/src/test/java/tests/org/w3c/dom/GetAttributeNodeNS.java new file mode 100644 index 0000000..7c72fe5 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/GetAttributeNodeNS.java @@ -0,0 +1,121 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getAttributeNodeNS(namespaceURI,localName)" method retrieves an + * attribute node by local name and NamespaceURI. + * + * Retrieve the first emp:address element node. The getAttributeNodeNS method + * returns an Attr node, the "value" can be examined to ensure the proper + * attribute node was retrieved. This attribute value should be null since there + * is no such attribute. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAtNodeNS</a> + */ +@TestTargetClass(Element.class) +public final class GetAttributeNodeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getAttributeNodeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetAttributeNodeNS1() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String localName = "invalidlocalname"; + Document doc; + NodeList elementList; + Element testAddr; + Attr attribute; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + attribute = testAddr.getAttributeNodeNS(namespaceURI, localName); + assertNull("throw_Null", attribute); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getAttributeNodeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetAttributeNodeNS2() throws Throwable { + Document doc; + NodeList elementList; + Element testAddr; + Attr attribute; + String attrName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + attribute = testAddr.getAttributeNodeNS("http://www.nist.gov", + "domestic"); + attrName = attribute.getNodeName(); + assertEquals("attrName", "emp:domestic", attrName); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/GetElementById.java b/xml/src/test/java/tests/org/w3c/dom/GetElementById.java new file mode 100644 index 0000000..073df2f --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/GetElementById.java @@ -0,0 +1,102 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2003 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getElementById(elementId)" method for a Document should return an + * element whose ID matches elementId. + * + * Invoke method getElementById(elementId) on this document with elementId + * equals "CANADA". Method should return an element whose tag name is + * "emp:address". + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-104682815">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-104682815</a> + * @see <a + * href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=383">http://www.w3.org/Bugs/Public/show_bug.cgi?id=383</a> + */ +@TestTargetClass(Document.class) +public final class GetElementById extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testGetElementById1() throws Throwable { +// Document doc; +// Element element; +// String tagname; +// doc = (Document) load("staffNS", builder); +// element = doc.getElementById("CANADA"); +// tagname = element.getTagName(); +// assertEquals("throw_Equals", "emp:address", tagname); +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify getElementById method for existent element.", + method = "getElementById", + args = {java.lang.String.class} + ) + public void testGetElementById2() throws Throwable { + Document doc; + Element element; + doc = (Document) load("staffNS", builder); + element = doc.getElementById("Cancun"); + assertNull("throw_Null", element); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/GetElementsByTagNameNS.java b/xml/src/test/java/tests/org/w3c/dom/GetElementsByTagNameNS.java new file mode 100644 index 0000000..d5fa0bf --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/GetElementsByTagNameNS.java @@ -0,0 +1,381 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getElementsByTagNameNS(namespaceURI,localName)" method for a Document + * should return a new NodeList of all Elements that have a namespace when local + * name is specified as ' '. + * + * Invoke method getElementsByTagNameNS(namespaceURI,localName) on this document + * with namespaceURI and localName as " ". Method should return a new NodeList + * of 37 elements. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS</a> + */ +@TestTargetClass(Document.class) +public final class GetElementsByTagNameNS extends DOMTestCase { + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies getElementsByTagNameNS method with * as parameters.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS1() throws Throwable { + String namespaceURI = "*"; + String localName = "*"; + Document doc; + NodeList newList; + doc = (Document) load("staffNS", builder); + newList = doc.getElementsByTagNameNS(namespaceURI, localName); + // BEGIN android-changed: Was 37, but that assumed validation. + assertEquals("throw_Size", 36, newList.getLength()); + // END android-changed + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies getElementsByTagNameNS with '*' as the first parameter.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS2() throws Throwable { + Document doc; + NodeList newList; + Element newElement; + String prefix; + String lname; + doc = (Document) load("staffNS", builder); + newList = doc.getElementsByTagNameNS("*", "employee"); + assertEquals("employeeCount", 5, newList.getLength()); + newElement = (Element) newList.item(3); + prefix = newElement.getPrefix(); + assertEquals("prefix", "emp", prefix); + lname = newElement.getLocalName(); + assertEquals("lname", "employee", lname); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies getElementsByTagNameNS with '*' as the second parameter.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS3() throws Throwable { + Document doc; + NodeList elementList; + Node child; + String childName; + List<String> result = new ArrayList<String>(); + + List<String> expectedResult = new ArrayList<String>(); + expectedResult.add("employee"); + expectedResult.add("employeeId"); + expectedResult.add("name"); + expectedResult.add("position"); + expectedResult.add("salary"); + expectedResult.add("gender"); + expectedResult.add("address"); + expectedResult.add("emp:employee"); + expectedResult.add("emp:employeeId"); + expectedResult.add("emp:position"); + expectedResult.add("emp:salary"); + expectedResult.add("emp:gender"); + expectedResult.add("emp:address"); + expectedResult.add("address"); + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", "*"); + for (int indexN10076 = 0; indexN10076 < elementList.getLength(); indexN10076++) { + child = (Node) elementList.item(indexN10076); + childName = child.getNodeName(); + result.add(childName); + } + assertEquals("nodeNames", expectedResult, result); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies getElementsByTagNameNS with '*' as the first parameter.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS4() throws Throwable { + Document doc; + NodeList elementList; + Node child; + String childName; + List<String> result = new ArrayList<String>(); + + List<String> expectedResult = new ArrayList<String>(); + expectedResult.add("address"); + expectedResult.add("address"); + expectedResult.add("address"); + expectedResult.add("emp:address"); + expectedResult.add("address"); + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + for (int indexN10059 = 0; indexN10059 < elementList.getLength(); indexN10059++) { + child = (Node) elementList.item(indexN10059); + childName = child.getNodeName(); + result.add(childName); + } + assertEquals("nodeNames", expectedResult, result); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies negative case of getElementsByTagNameNS method.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS5() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String localName = "nomatch"; + Document doc; + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS(namespaceURI, localName); + assertEquals("throw_Size", 0, elementList.getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies negative case of getElementsByTagNameNS method.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS6() throws Throwable { + Document doc; + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nomatch.com", + "address"); + assertEquals("matchSize", 0, elementList.getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive case of getElementsByTagNameNS method.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS7() throws Throwable { + Document doc; + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "address"); + assertEquals("addresses", 3, elementList.getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies getElementsByTagNameNS method with '*' as parameters; positive case.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS8() throws Throwable { + Document doc; + Element docElem; + NodeList newList; + doc = (Document) load("staffNS", builder); + docElem = doc.getDocumentElement(); + newList = docElem.getElementsByTagNameNS("*", "*"); + assertEquals("listSize", 36, newList.getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies getElementsByTagNameNS method with '*' as the first parameter.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS9() throws Throwable { + Document doc; + NodeList newList; + Element newElement; + String prefix; + String lname; + Element docElem; + doc = (Document) load("staffNS", builder); + docElem = doc.getDocumentElement(); + newList = docElem.getElementsByTagNameNS("*", "employee"); + assertEquals("employeeCount", 5, newList.getLength()); + newElement = (Element) newList.item(3); + prefix = newElement.getPrefix(); + assertEquals("prefix", "emp", prefix); + lname = newElement.getLocalName(); + assertEquals("lname", "employee", lname); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies getElementsByTagNameNS method with '*' as the second parameter.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS10() throws Throwable { + Document doc; + Element docElem; + NodeList elementList; + Node child; + String childName; + List<String> result = new ArrayList<String>(); + + List<String> expectedResult = new ArrayList<String>(); + expectedResult.add("employee"); + expectedResult.add("employeeId"); + expectedResult.add("name"); + expectedResult.add("position"); + expectedResult.add("salary"); + expectedResult.add("gender"); + expectedResult.add("address"); + expectedResult.add("emp:employee"); + expectedResult.add("emp:employeeId"); + expectedResult.add("emp:position"); + expectedResult.add("emp:salary"); + expectedResult.add("emp:gender"); + expectedResult.add("emp:address"); + expectedResult.add("address"); + + doc = (Document) load("staffNS", builder); + docElem = doc.getDocumentElement(); + elementList = docElem + .getElementsByTagNameNS("http://www.nist.gov", "*"); + for (int indexN1007E = 0; indexN1007E < elementList.getLength(); indexN1007E++) { + child = (Node) elementList.item(indexN1007E); + childName = child.getNodeName(); + result.add(childName); + } + assertEquals("nodeNames", expectedResult, result); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies getElementsByTagNameNS method with '*' as the first parameter.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS11() throws Throwable { + Document doc; + Element docElem; + NodeList elementList; + Node child; + String childName; + List<String> result = new ArrayList<String>(); + + List<String> expectedResult = new ArrayList<String>(); + expectedResult.add("address"); + expectedResult.add("address"); + expectedResult.add("address"); + expectedResult.add("emp:address"); + expectedResult.add("address"); + + doc = (Document) load("staffNS", builder); + docElem = doc.getDocumentElement(); + elementList = docElem.getElementsByTagNameNS("*", "address"); + for (int indexN1005E = 0; indexN1005E < elementList.getLength(); indexN1005E++) { + child = (Node) elementList.item(indexN1005E); + childName = child.getNodeName(); + result.add(childName); + } + assertEquals("nodeNames", expectedResult, result); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies negative case for getElementsByTagNameNS method.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS12() throws Throwable { + Document doc; + Element docElem; + NodeList elementList; + doc = (Document) load("staffNS", builder); + docElem = doc.getDocumentElement(); + elementList = docElem.getElementsByTagNameNS("http://www.nist.gov", + "nomatch"); + assertEquals("size", 0, elementList.getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies negative case for getElementsByTagNameNS method.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS13() throws Throwable { + Document doc; + Element docElem; + NodeList elementList; + doc = (Document) load("staffNS", builder); + docElem = doc.getDocumentElement(); + elementList = docElem.getElementsByTagNameNS("http://www.nomatch.com", + "address"); + assertEquals("matchSize", 0, elementList.getLength()); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive case for getElementsByTagNameNS method.", + method = "getElementsByTagNameNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetElementsByTagNameNS14() throws Throwable { + Document doc; + Element docElem; + NodeList elementList; + doc = (Document) load("staffNS", builder); + docElem = doc.getDocumentElement(); + elementList = docElem.getElementsByTagNameNS("http://www.nist.gov", + "address"); + assertEquals("addresses", 3, elementList.getLength()); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/GetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/GetNamedItemNS.java new file mode 100644 index 0000000..270fe04 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/GetNamedItemNS.java @@ -0,0 +1,135 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.Attr; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getNamedItemNS(namespaceURI,localName)" method for a NamedNodeMap should + * return a node specified by localName and namespaceURI + * + * Retrieve a list of elements with tag name "address". Access the second + * element from the list and get its attributes. Try to retrieve the attribute + * node with local name "domestic" and namespace uri "http://www.usa.com" with + * method getNamedItemNS(namespaceURI,localName). + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class GetNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getNamedItem", + args = {java.lang.String.class} + ) + public void testGetNamedItemNS1() throws Throwable { + Document doc; + NodeList elementList; + Node testEmployee; + NamedNodeMap attributes; + Attr domesticAttr; + String attrName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + testEmployee = elementList.item(1); + attributes = testEmployee.getAttributes(); + domesticAttr = (Attr) attributes.getNamedItemNS("http://www.usa.com", + "domestic"); + attrName = domesticAttr.getNodeName(); + assertEquals("attrName", "dmstc:domestic", attrName); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetNamedItemNS2() throws Throwable { + String namespaceURI = "http://www.usa.com"; + String localName = "domest"; + Document doc; + NodeList elementList; + Node testEmployee; + NamedNodeMap attributes; + Attr newAttr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + testEmployee = elementList.item(1); + attributes = testEmployee.getAttributes(); + newAttr = (Attr) attributes.getNamedItemNS(namespaceURI, localName); + assertNull("throw_Null", newAttr); + } + +// Assumes validation. +// public void testGetNamedItemNS3() throws Throwable { +// Document doc; +// DocumentType docType; +// NamedNodeMap entities; +// Entity entity; +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// entities = docType.getEntities(); +// assertNotNull("entitiesNotNull", entities); +// entity = (Entity) entities.getNamedItemNS(nullNS, "ent1"); +// assertNotNull("entityNull", entity); +// } + +// Assumes validation. +// public void testGetNamedItemNS4() throws Throwable { +// Document doc; +// DocumentType docType; +// NamedNodeMap notations; +// Notation notation; +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// notations = docType.getNotations(); +// assertNotNull("notationsNotNull", notations); +// notation = (Notation) notations.getNamedItemNS(nullNS, "notation1"); +// assertNotNull("notationNull", notation); +// } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HCEntitiesRemoveNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/HCEntitiesRemoveNamedItemNS.java new file mode 100644 index 0000000..1cdd20f --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HCEntitiesRemoveNamedItemNS.java @@ -0,0 +1,102 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + Copyright (c) 2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargetClass; + +import javax.xml.parsers.DocumentBuilder; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.NamedNodeMap; + +/** + * An attempt to add remove an entity using removeNamedItemNS should result in a + * NO_MODIFICATION_ERR or a NOT_FOUND_ERR. + * + * @author Curt Arnold + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1788794630">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1788794630</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-removeNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-removeNamedItemNS</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class HCEntitiesRemoveNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testRemoveNamedItemNS() throws Throwable { +// Document doc; +// NamedNodeMap entities; +// DocumentType docType; +// +// doc = (Document) load("hc_staff", builder); +// docType = doc.getDoctype(); +// +// if (!(("text/html".equals(getContentType())))) { +// assertNotNull("docTypeNotNull", docType); +// entities = docType.getEntities(); +// assertNotNull("entitiesNotNull", entities); +// +// try { +// entities.removeNamedItemNS( +// "http://www.w3.org/1999/xhtml", "alpha"); +// fail("throw_NO_MOD_OR_NOT_FOUND_ERR"); +// +// } catch (DOMException ex) { +// switch (ex.code) { +// case 7: +// break; +// case 8: +// break; +// default: +// throw ex; +// } +// } +// } +// } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HCEntitiesSetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/HCEntitiesSetNamedItemNS.java new file mode 100644 index 0000000..7e2917a --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HCEntitiesSetNamedItemNS.java @@ -0,0 +1,86 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargetClass; + +import javax.xml.parsers.DocumentBuilder; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; + +/** + * An attempt to add an element to the named node map returned by entities + * should result in a NO_MODIFICATION_ERR or HIERARCHY_REQUEST_ERR. + * + * @author Curt Arnold + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1788794630">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1788794630</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class HCEntitiesSetNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testSetNamedItemNS() throws Throwable { +// Document doc; +// NamedNodeMap entities; +// DocumentType docType; +// +// Element elem; +// doc = (Document) load("hc_staff", builder); +// docType = doc.getDoctype(); +// +// if (!(("text/html".equals(getContentType())))) { +// assertNotNull("docTypeNotNull", docType); +// entities = docType.getEntities(); +// assertNotNull("entitiesNotNull", entities); +// elem = doc.createElementNS("http://www.w3.org/1999/xhtml", "br"); +// +// try { +// entities.setNamedItemNS(elem); +// fail("throw_HIER_OR_NO_MOD_ERR"); +// +// } catch (DOMException ex) { +// switch (ex.code) { +// case 3: +// break; +// case 7: +// break; +// default: +// throw ex; +// } +// } +// } +// } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HCNamedNodeMapInvalidType.java b/xml/src/test/java/tests/org/w3c/dom/HCNamedNodeMapInvalidType.java new file mode 100644 index 0000000..d968bc4 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HCNamedNodeMapInvalidType.java @@ -0,0 +1,103 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + Copyright (c) 2001-2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * Attempt to insert an element into an attribute list, should raise a + * HIERARCHY_REQUEST_ERR. + * + * @author Curt Arnold + * @see <a + * href="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core#xpointer(id('ID-258A00AF')/constant[@name='HIERARCHY_REQUEST_ERR'])">http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core#xpointer(id('ID-258A00AF')/constant[@name='HIERARCHY_REQUEST_ERR'])</a> + * @see <a + * href="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core#ID-1025163788">http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core#ID-1025163788</a> + * @see <a + * href="http://www.w3.org/2000/11/DOM-Level-2-errata#core-4">http://www.w3.org/2000/11/DOM-Level-2-errata#core-4</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class HCNamedNodeMapInvalidType extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that setNamedItem method throws DOMException with HIERARCHY_REQUEST_ERR code.", + method = "setNamedItem", + args = {org.w3c.dom.Node.class} + ) + public void testNamedNodeMapInvalidType() throws Throwable { + Document doc; + NamedNodeMap attributes; + Element docElem; + Element newElem; + + doc = (Document) load("hc_staff", builder); + docElem = doc.getDocumentElement(); + attributes = docElem.getAttributes(); + newElem = doc.createElement("html"); + + { + boolean success = false; + try { + attributes.setNamedItem(newElem); + } catch (DOMException ex) { + success = (ex.code == DOMException.HIERARCHY_REQUEST_ERR); + } + assertTrue("throw_HIERARCHY_REQUEST_ERR", success); + } + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HCNodeDocumentFragmentNormalize.java b/xml/src/test/java/tests/org/w3c/dom/HCNodeDocumentFragmentNormalize.java new file mode 100644 index 0000000..53317b3 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HCNodeDocumentFragmentNormalize.java @@ -0,0 +1,108 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Text; + +import javax.xml.parsers.DocumentBuilder; + +/** + * Create a document fragment with two adjacent text nodes, normalize and see if + * the text nodes were combined. + * + * @author Curt Arnold + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-B63ED1A3">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-B63ED1A3</a> + */ +@TestTargetClass(Node.class) +public final class HCNodeDocumentFragmentNormalize extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargets({ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies positive functionality of getNodeValue method, and that getNextSibling method returns null.", + method = "getNodeValue", + args = {} + ), + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies positive functionality of getNodeValue method, and that getNextSibling method returns null.", + method = "getNextSibling", + args = {} + ) + }) + public void testNodeDocumentFragmentNormalize1() throws Throwable { + Document doc; + DocumentFragment docFragment; + String nodeValue; + Text txtNode; + Node retval; + + doc = (Document) load("hc_staff", builder); + docFragment = doc.createDocumentFragment(); + txtNode = doc.createTextNode("foo"); + retval = docFragment.appendChild(txtNode); + txtNode = doc.createTextNode("bar"); + retval = docFragment.appendChild(txtNode); + docFragment.normalize(); + txtNode = (Text) docFragment.getFirstChild(); + nodeValue = txtNode.getNodeValue(); + assertEquals("normalizedNodeValue", "foobar", nodeValue); + retval = txtNode.getNextSibling(); + assertNull("singleChild", retval); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getFirstChild method returns null.", + method = "getFirstChild", + args = {} + ) + public void testNodeDocumentFragmentNormalize2() throws Throwable { + Document doc; + DocumentFragment docFragment; + Text txtNode; + + doc = (Document) load("hc_staff", builder); + docFragment = doc.createDocumentFragment(); + txtNode = doc.createTextNode(""); + docFragment.appendChild(txtNode); + docFragment.normalize(); + txtNode = (Text) docFragment.getFirstChild(); + assertNull("noChild", txtNode); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HCNotationsRemoveNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/HCNotationsRemoveNamedItemNS.java new file mode 100644 index 0000000..3eab5fc --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HCNotationsRemoveNamedItemNS.java @@ -0,0 +1,110 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + Copyright (c) 2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * An attempt to add remove an notation using removeNamedItemNS should result in + * a NO_MODIFICATION_ERR or a NOT_FOUND_ERR. + * + * @author Curt Arnold + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D46829EF">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D46829EF</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-removeNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-removeNamedItemNS</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class HCNotationsRemoveNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that removeNamedItemNS method throws DOMException.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS() throws Throwable { + Document doc; + NamedNodeMap notations; + DocumentType docType; + + doc = (Document) load("hc_staff", builder); + docType = doc.getDoctype(); + + if (!(("text/html".equals(getContentType())))) { + assertNotNull("docTypeNotNull", docType); + notations = docType.getNotations(); + assertNotNull("notationsNotNull", notations); + + try { + notations.removeNamedItemNS("http://www.w3.org/1999/xhtml", + "alpha"); + fail("throw_NO_MOD_OR_NOT_FOUND_ERR"); + + } catch (DOMException ex) { + switch (ex.code) { + case 7: + break; + case 8: + break; + default: + throw ex; + } + } + } + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HCNotationsSetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/HCNotationsSetNamedItemNS.java new file mode 100644 index 0000000..d5daee4 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HCNotationsSetNamedItemNS.java @@ -0,0 +1,112 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + Copyright (c) 2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * An attempt to add an element to the named node map returned by notations + * should result in a NO_MODIFICATION_ERR or HIERARCHY_REQUEST_ERR. + * + * @author Curt Arnold + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D46829EF">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D46829EF</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class HCNotationsSetNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that setNamedItemNS throws DOMException.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testNotationsSetNamedItemNS() throws Throwable { + Document doc; + NamedNodeMap notations; + DocumentType docType; + + Element elem; + doc = (Document) load("hc_staff", builder); + docType = doc.getDoctype(); + + if (!(("text/html".equals(getContentType())))) { + assertNotNull("docTypeNotNull", docType); + notations = docType.getNotations(); + assertNotNull("notationsNotNull", notations); + elem = doc.createElementNS("http://www.w3.org/1999/xhtml", "br"); + + try { + notations.setNamedItemNS(elem); + fail("throw_HIER_OR_NO_MOD_ERR"); + + } catch (DOMException ex) { + switch (ex.code) { + case 3: + break; + case 7: + break; + default: + throw ex; + } + } + } + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HasAttribute.java b/xml/src/test/java/tests/org/w3c/dom/HasAttribute.java new file mode 100644 index 0000000..89eef88 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HasAttribute.java @@ -0,0 +1,119 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "hasAttribute()" method for an Element should return true if the element + * has an attribute with the given name. Retrieve the first "address" element + * and the "hasAttribute()" method should return false since the element does + * not have a default value. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttr">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttr</a> + */ +@TestTargetClass(Element.class) +public final class HasAttribute extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that hasAttribute method returns false.", + method = "hasAttribute", + args = {java.lang.String.class} + ) + public void testHasAttribute1() throws Throwable { + Document doc; + NodeList elementList; + Element testNode; + boolean state; + doc = (Document) load("staff", builder); + elementList = doc.getElementsByTagName("address"); + testNode = (Element) elementList.item(4); + state = testNode.hasAttribute("domestic"); + assertFalse("throw_False", state); + } + +// Assumes validation. +// public void testHasAttribute2() throws Throwable { +// Document doc; +// NodeList elementList; +// Element testNode; +// boolean state; +// doc = (Document) load("staff", builder); +// elementList = doc.getElementsByTagName("address"); +// testNode = (Element) elementList.item(0); +// state = testNode.hasAttribute("street"); +// assertTrue("throw_True", state); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that hasAttribute method returns false.", + method = "hasAttribute", + args = {java.lang.String.class} + ) + public void testHasAttribute3() throws Throwable { + Document doc; + NodeList elementList; + Element testNode; + boolean state; + doc = (Document) load("staff", builder); + elementList = doc.getElementsByTagName("address"); + testNode = (Element) elementList.item(0); + state = testNode.hasAttribute("nomatch"); + assertFalse("throw_False", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that hasAttribute method returns true.", + method = "hasAttribute", + args = {java.lang.String.class} + ) + public void testHasAttribute4() throws Throwable { + Document doc; + NodeList elementList; + Element testNode; + boolean state; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + testNode = (Element) elementList.item(0); + state = testNode.hasAttribute("dmstc:domestic"); + assertTrue("hasDomesticAttr", state); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HasAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/HasAttributeNS.java new file mode 100644 index 0000000..cf1b90e --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HasAttributeNS.java @@ -0,0 +1,172 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; + +/** + * + * The "hasAttributeNS()" method for an Element should return false if the + * element does not have an attribute with the given local name and/or a + * namespace URI specified on this element or does not have a default value. + * Retrieve the first "address" element and the "hasAttributeNS()" method should + * return false since the element has "nomatch" as the local name and + * "http://www.usa.com" as the namespace URI. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttrNS</a> + */ +@TestTargetClass(Element.class) +public final class HasAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "hasAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasAttributeNS1() throws Throwable { + String localName = "nomatch"; + String namespaceURI = "http://www.usa.com"; + Document doc; + NodeList elementList; + Element testNode; + boolean state; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + testNode = (Element) elementList.item(0); + state = testNode.hasAttributeNS(namespaceURI, localName); + assertFalse("throw_False", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "hasAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasAttributeNS2() throws Throwable { + String localName = "domestic"; + String namespaceURI = "http://www.nomatch.com"; + Document doc; + NodeList elementList; + Element testNode; + boolean state; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + testNode = (Element) elementList.item(0); + state = testNode.hasAttributeNS(namespaceURI, localName); + assertFalse("throw_False", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "hasAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasAttributeNS3() throws Throwable { + String localName = "blank"; + String namespaceURI = "http://www.nist.gov"; + Document doc; + NodeList elementList; + Element testNode; + boolean state; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testNode = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", testNode); + state = testNode.hasAttributeNS(namespaceURI, localName); + assertFalse("throw_False", state); + } + +// Assumes validation. +// public void testHasAttributeNS4() throws Throwable { +// String localName = "district"; +// String namespaceURI = "http://www.nist.gov"; +// Document doc; +// NodeList elementList; +// Element testNode; +// boolean state; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("emp:address"); +// testNode = (Element) elementList.item(0); +// assertNotNull("empAddressNotNull", testNode); +// state = testNode.hasAttributeNS(namespaceURI, localName); +// assertTrue("hasAttribute", state); +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "hasAttributeNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testHasAttributeNS5() throws Throwable { + String localName = "domestic"; + String namespaceURI = "http://www.usa.com"; + Document doc; + NodeList elementList; + Element testNode; + boolean state; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + testNode = (Element) elementList.item(0); + state = testNode.hasAttributeNS(namespaceURI, localName); + assertTrue("hasAttribute", state); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/HasAttributes.java b/xml/src/test/java/tests/org/w3c/dom/HasAttributes.java new file mode 100644 index 0000000..5d3954d --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/HasAttributes.java @@ -0,0 +1,111 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "hasAttributes()" method for a node should return false if the node does + * not have an attribute. Retrieve the first "name" node and invoke the + * "hasAttributes()" method. The method should return false since the node does + * not have an attribute. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs</a> + */ +@TestTargetClass(Node.class) +public final class HasAttributes extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that hasAttributes method returns false value.", + method = "hasAttributes", + args = {} + ) + public void testHasAttributes1() throws Throwable { + Document doc; + NodeList addrList; + Node addrNode; + boolean state; + doc = (Document) load("staff", builder); + addrList = doc.getElementsByTagName("name"); + addrNode = addrList.item(0); + state = addrNode.hasAttributes(); + assertFalse("throw_False", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that hasAttributes method returns true value.", + method = "hasAttributes", + args = {} + ) + public void testHasAttributes2() throws Throwable { + Document doc; + NodeList addrList; + Node addrNode; + boolean state; + doc = (Document) load("staff", builder); + addrList = doc.getElementsByTagName("address"); + addrNode = addrList.item(0); + state = addrNode.hasAttributes(); + assertTrue("throw_True", state); + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/ImportNode.java b/xml/src/test/java/tests/org/w3c/dom/ImportNode.java new file mode 100644 index 0000000..de39392 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/ImportNode.java @@ -0,0 +1,604 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Attr; +import org.w3c.dom.Text; +import org.w3c.dom.Node; +import org.w3c.dom.Element; +import org.w3c.dom.DocumentType; +import org.w3c.dom.NodeList; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.EntityReference; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "importNode(importedNode,deep)" method for a Document should import the + * given importedNode into that Document. The importedNode is of type Attr. The + * ownerElement is set to null. Specified flag is set to true. Children is + * imported. + * + * Create a new attribute whose name is "elem:attr1" in a different document. + * Create a child Text node with value "importedText" for the attribute node + * above. Invoke method importNode(importedNode,deep) on this document with + * importedNode being the newly created attribute. Method should return a node + * whose name matches "elem:attr1" and a child node whose value equals + * "importedText". The returned node should belong to this document whose + * systemId is "staff.dtd" + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#Core-Document-importNode">http://www.w3.org/TR/DOM-Level-2-Core/core#Core-Document-importNode</a> + */ +@TestTargetClass(Document.class) +public final class ImportNode extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void _testImportNode1() throws Throwable { + Document doc; + Document aNewDoc; + Attr newAttr; + Text importedChild; + Node aNode; + Document ownerDocument; + Element attrOwnerElement; + DocumentType docType; + String system; + boolean specified; + NodeList childList; + String nodeName; + Node child; + String childValue; + List<String> expectedResult = new ArrayList<String>(); + expectedResult.add("elem:attr1"); + expectedResult.add("importedText"); + + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + newAttr = aNewDoc.createAttribute("elem:attr1"); + importedChild = aNewDoc.createTextNode("importedText"); + aNode = newAttr.appendChild(importedChild); + aNode = doc.importNode(newAttr, false); + ownerDocument = aNode.getOwnerDocument(); + docType = ownerDocument.getDoctype(); + system = docType.getSystemId(); + assertNotNull("aNode", aNode); + assertURIEquals("systemId", null, null, null, "staffNS.dtd", null, + null, null, null, system); + attrOwnerElement = ((Attr) /* Node */aNode).getOwnerElement(); + assertNull("ownerElement", attrOwnerElement); + specified = ((Attr) /* Node */aNode).getSpecified(); + assertTrue("specified", specified); + childList = aNode.getChildNodes(); + assertEquals("childList", 1, childList.getLength()); + nodeName = aNode.getNodeName(); + assertEquals("nodeName", "elem:attr1", nodeName); + child = aNode.getFirstChild(); + childValue = child.getNodeValue(); + assertEquals("childValue", "importedText", childValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode2() throws Throwable { + Document doc; + Document aNewDoc; + CDATASection cDataSec; + Node aNode; + Document ownerDocument; + DocumentType docType; + String system; + String value; + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + cDataSec = aNewDoc.createCDATASection("this is CDATASection data"); + aNode = doc.importNode(cDataSec, false); + ownerDocument = aNode.getOwnerDocument(); + assertNotNull("ownerDocumentNotNull", ownerDocument); + docType = ownerDocument.getDoctype(); + system = docType.getSystemId(); + assertURIEquals("dtdSystemId", null, null, null, "staffNS.dtd", null, + null, null, null, system); + value = aNode.getNodeValue(); + assertEquals("nodeValue", "this is CDATASection data", value); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode3() throws Throwable { + Document doc; + Document aNewDoc; + Comment comment; + Node aNode; + Document ownerDocument; + DocumentType docType; + String system; + String value; + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + comment = aNewDoc.createComment("this is a comment"); + aNode = doc.importNode(comment, false); + ownerDocument = aNode.getOwnerDocument(); + assertNotNull("ownerDocumentNotNull", ownerDocument); + docType = ownerDocument.getDoctype(); + system = docType.getSystemId(); + assertURIEquals("systemId", null, null, null, "staffNS.dtd", null, + null, null, null, system); + value = aNode.getNodeValue(); + assertEquals("nodeValue", "this is a comment", value); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode4() throws Throwable { + Document doc; + Document aNewDoc; + DocumentFragment docFrag; + Comment comment; + Node aNode; + NodeList children; + Node child; + String childValue; + doc = (Document) load("staff", builder); + aNewDoc = (Document) load("staff", builder); + docFrag = aNewDoc.createDocumentFragment(); + comment = aNewDoc.createComment("descendant1"); + aNode = docFrag.appendChild(comment); + aNode = doc.importNode(docFrag, true); + children = aNode.getChildNodes(); + assertEquals("throw_Size", 1, children.getLength()); + child = aNode.getFirstChild(); + childValue = child.getNodeValue(); + assertEquals("descendant1", "descendant1", childValue); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode5() throws Throwable { + Document doc; + Document aNewDoc; + Element element; + Node aNode; + boolean hasChild; + Document ownerDocument; + DocumentType docType; + String system; + String name; + NodeList addresses; + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + addresses = aNewDoc.getElementsByTagName("emp:address"); + element = (Element) addresses.item(0); + assertNotNull("empAddressNotNull", element); + aNode = doc.importNode(element, false); + hasChild = aNode.hasChildNodes(); + assertFalse("hasChild", hasChild); + ownerDocument = aNode.getOwnerDocument(); + docType = ownerDocument.getDoctype(); + system = docType.getSystemId(); + assertURIEquals("dtdSystemId", null, null, null, "staffNS.dtd", null, + null, null, null, system); + name = aNode.getNodeName(); + assertEquals("nodeName", "emp:address", name); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode6() throws Throwable { + Document doc; + Document aNewDoc; + Element element; + Node aNode; + boolean hasChild; + String name; + Node child; + String value; + NodeList addresses; + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + addresses = aNewDoc.getElementsByTagName("emp:address"); + element = (Element) addresses.item(0); + assertNotNull("empAddressNotNull", element); + aNode = doc.importNode(element, true); + hasChild = aNode.hasChildNodes(); + assertTrue("throw_True", hasChild); + name = aNode.getNodeName(); + assertEquals("nodeName", "emp:address", name); + child = aNode.getFirstChild(); + value = child.getNodeValue(); + assertEquals("nodeValue", "27 South Road. Dallas, texas 98556", value); + } + +// Assumes validation. +// public void testImportNode7() throws Throwable { +// Document doc; +// Document aNewDoc; +// Element element; +// Node aNode; +// NamedNodeMap attributes; +// String name; +// Node attr; +// String lname; +// String namespaceURI = "http://www.nist.gov"; +// String qualifiedName = "emp:employee"; +// doc = (Document) load("staffNS", builder); +// aNewDoc = (Document) load("staff", builder); +// element = aNewDoc.createElementNS(namespaceURI, qualifiedName); +// aNode = doc.importNode(element, false); +// attributes = aNode.getAttributes(); +// assertEquals("throw_Size", 1, attributes.getLength()); +// name = aNode.getNodeName(); +// assertEquals("nodeName", "emp:employee", name); +// attr = attributes.item(0); +// lname = attr.getLocalName(); +// assertEquals("lname", "defaultAttr", lname); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode8() throws Throwable { + Document doc; + Document aNewDoc; + DocumentFragment docFrag; + Node aNode; + boolean hasChild; + Document ownerDocument; + DocumentType docType; + String system; + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + docFrag = aNewDoc.createDocumentFragment(); + aNode = doc.importNode(docFrag, false); + hasChild = aNode.hasChildNodes(); + assertFalse("hasChild", hasChild); + ownerDocument = aNode.getOwnerDocument(); + docType = ownerDocument.getDoctype(); + system = docType.getSystemId(); + assertURIEquals("system", null, null, null, "staffNS.dtd", null, null, + null, null, system); + } + +// Assumes validation. +// public void testImportNode9() throws Throwable { +// Document doc; +// Document aNewDoc; +// +// NamedNodeMap entityList; +// Entity entity2; +// Entity entity1; +// Document ownerDocument; +// DocumentType docType; +// String system; +// String entityName; +// String publicVal; +// String notationName; +// doc = (Document) load("staffNS", builder); +// aNewDoc = (Document) load("staffNS", builder); +// docType = aNewDoc.getDoctype(); +// entityList = docType.getEntities(); +// assertNotNull("entitiesNotNull", entityList); +// entity2 = (Entity) entityList.getNamedItem("ent6"); +// entity1 = (Entity) doc.importNode(entity2, false); +// ownerDocument = entity1.getOwnerDocument(); +// docType = ownerDocument.getDoctype(); +// system = docType.getSystemId(); +// assertURIEquals("dtdSystemId", null, null, null, "staffNS.dtd", null, +// null, null, null, system); +// entityName = entity1.getNodeName(); +// assertEquals("entityName", "ent6", entityName); +// publicVal = entity1.getPublicId(); +// assertEquals("entityPublicId", "uri", publicVal); +// system = entity1.getSystemId(); +// assertURIEquals("entitySystemId", null, null, null, "file", null, null, +// null, null, system); +// notationName = entity1.getNotationName(); +// assertEquals("notationName", "notation2", notationName); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode10() throws Throwable { + Document doc; + Document aNewDoc; + EntityReference entRef; + Node aNode; + Document ownerDocument; + DocumentType docType; + String system; + String name; + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + entRef = aNewDoc.createEntityReference("entRef1"); + assertNotNull("createdEntRefNotNull", entRef); + entRef.setNodeValue("entRef1Value"); + aNode = doc.importNode(entRef, false); + ownerDocument = aNode.getOwnerDocument(); + docType = ownerDocument.getDoctype(); + system = docType.getSystemId(); + assertURIEquals("systemId", null, null, null, "staffNS.dtd", null, + null, null, null, system); + name = aNode.getNodeName(); + assertEquals("nodeName", "entRef1", name); + } + +// Assumes validation +// public void testImportNode11() throws Throwable { +// Document doc; +// Document aNewDoc; +// EntityReference entRef; +// Node aNode; +// String name; +// Node child; +// String childValue; +// doc = (Document) load("staff", builder); +// aNewDoc = (Document) load("staff", builder); +// entRef = aNewDoc.createEntityReference("ent3"); +// assertNotNull("createdEntRefNotNull", entRef); +// aNode = doc.importNode(entRef, true); +// name = aNode.getNodeName(); +// assertEquals("entityName", "ent3", name); +// child = aNode.getFirstChild(); +// assertNotNull("child", child); +// childValue = child.getNodeValue(); +// assertEquals("childValue", "Texas", childValue); +// } + +// Assumes validation. +// public void testImportNode12() throws Throwable { +// Document doc; +// Document aNewDoc; +// DocumentType doc1Type; +// NamedNodeMap entityList; +// Entity entity2; +// Entity entity1; +// Document ownerDocument; +// DocumentType docType; +// String system; +// String entityName; +// Node child; +// String childName; +// doc = (Document) load("staffNS", builder); +// aNewDoc = (Document) load("staffNS", builder); +// doc1Type = aNewDoc.getDoctype(); +// entityList = doc1Type.getEntities(); +// assertNotNull("entitiesNotNull", entityList); +// entity2 = (Entity) entityList.getNamedItem("ent4"); +// entity1 = (Entity) doc.importNode(entity2, true); +// ownerDocument = entity1.getOwnerDocument(); +// docType = ownerDocument.getDoctype(); +// system = docType.getSystemId(); +// assertURIEquals("systemId", null, null, null, "staffNS.dtd", null, +// null, null, null, system); +// entityName = entity1.getNodeName(); +// assertEquals("entityName", "ent4", entityName); +// child = entity1.getFirstChild(); +// assertNotNull("notnull", child); +// childName = child.getNodeName(); +// assertEquals("childName", "entElement1", childName); +// } + +// Assumes validation +// public void testImportNode13() throws Throwable { +// Document doc; +// Document aNewDoc; +// DocumentType doc1Type; +// NamedNodeMap notationList; +// Notation notation; +// Notation aNode; +// Document ownerDocument; +// DocumentType docType; +// String system; +// String publicVal; +// doc = (Document) load("staffNS", builder); +// aNewDoc = (Document) load("staffNS", builder); +// doc1Type = aNewDoc.getDoctype(); +// notationList = doc1Type.getNotations(); +// assertNotNull("notationsNotNull", notationList); +// notation = (Notation) notationList.getNamedItem("notation1"); +// aNode = (Notation) doc.importNode(notation, false); +// ownerDocument = aNode.getOwnerDocument(); +// docType = ownerDocument.getDoctype(); +// system = docType.getSystemId(); +// assertURIEquals("systemId", null, null, null, "staffNS.dtd", null, +// null, null, null, system); +// publicVal = aNode.getPublicId(); +// assertEquals("publicId", "notation1File", publicVal); +// system = aNode.getSystemId(); +// assertNull("notationSystemId", system); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode14() throws Throwable { + Document doc; + Document aNewDoc; + ProcessingInstruction pi; + ProcessingInstruction aNode; + Document ownerDocument; + DocumentType docType; + String system; + String target; + String data; + + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + pi = aNewDoc.createProcessingInstruction("target1", "data1"); + aNode = (ProcessingInstruction) doc.importNode(pi, false); + ownerDocument = aNode.getOwnerDocument(); + assertNotNull("ownerDocumentNotNull", ownerDocument); + docType = ownerDocument.getDoctype(); + system = docType.getSystemId(); + assertURIEquals("systemId", null, null, null, "staffNS.dtd", null, + null, null, null, system); + target = aNode.getTarget(); + assertEquals("piTarget", "target1", target); + data = aNode.getData(); + assertEquals("piData", "data1", data); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode15() throws Throwable { + Document doc; + Document aNewDoc; + Text text; + Node aNode; + Document ownerDocument; + DocumentType docType; + String system; + String value; + doc = (Document) load("staffNS", builder); + aNewDoc = (Document) load("staffNS", builder); + text = aNewDoc.createTextNode("this is text data"); + aNode = doc.importNode(text, false); + ownerDocument = aNode.getOwnerDocument(); + assertNotNull("ownerDocumentNotNull", ownerDocument); + docType = ownerDocument.getDoctype(); + system = docType.getSystemId(); + assertURIEquals("systemId", null, null, null, "staffNS.dtd", null, + null, null, null, system); + value = aNode.getNodeValue(); + assertEquals("nodeValue", "this is text data", value); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode16() throws Throwable { + Document doc; + Document anotherDoc; + DocumentType docType; + + doc = (Document) load("staffNS", builder); + anotherDoc = (Document) load("staffNS", builder); + docType = anotherDoc.getDoctype(); + + { + boolean success = false; + try { + doc.importNode(docType, false); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_SUPPORTED_ERR); + } + assertTrue("throw_NOT_SUPPORTED_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.", + method = "importNode", + args = {org.w3c.dom.Node.class, boolean.class} + ) + public void testImportNode17() throws Throwable { + Document doc; + Document anotherDoc; + + doc = (Document) load("staffNS", builder); + anotherDoc = (Document) load("staffNS", builder); + + { + boolean success = false; + try { + doc.importNode(anotherDoc, false); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_SUPPORTED_ERR); + } + assertTrue("throw_NOT_SUPPORTED_ERR", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/InternalSubset.java b/xml/src/test/java/tests/org/w3c/dom/InternalSubset.java new file mode 100644 index 0000000..f8f306c --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/InternalSubset.java @@ -0,0 +1,92 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001-2004 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.DocumentType; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getInternalSubset()" method returns + * the internal subset as a string or null if there is none. + * This does not contain the delimiting brackets. + * + * Retrieve the documenttype. + * Apply the "getInternalSubset()" method. Null is returned since there + * is not an internal subset. +* @author NIST +* @author Mary Brady +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-internalSubset">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-internalSubset</a> +*/ +@TestTargetClass(DocumentType.class) +public final class InternalSubset extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify that getInternalSubset method returns the internal subset as a string.", + method = "getInternalSubset", + args = {} + ) + public void testGetInternalSubset() throws Throwable { + Document doc; + DocumentType docType; + String internal; + doc = (Document) load("staff2", builder); + docType = doc.getDoctype(); + internal = docType.getInternalSubset(); + assertNull("internalSubsetNull", internal); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/IsSupported.java b/xml/src/test/java/tests/org/w3c/dom/IsSupported.java new file mode 100644 index 0000000..318a81d --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/IsSupported.java @@ -0,0 +1,272 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "feature" parameter in the isSupported(feature,version)" method is the + * name of the feature and the version is the version number of the feature to + * test. XXX is NOT a legal value for the feature parameter. The method should + * return "false" since XXX is not a valid feature. + * + * Retrieve the root node of the DOM document by invoking the + * "getDocumentElement()" method. This should create a node object on which the + * "isSupported(feature,version)" method is invoked with "feature" equal to + * "XXX" and version to "1.0". The method should return a boolean "false" since + * XXX is not a valid feature. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-Node-supports">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-Node-supports</a> + */ +@TestTargetClass(Document.class) +public final class IsSupported extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns false.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported1() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("XXX", "1.0"); + assertFalse("throw_False", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns false value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported2() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("XML", "9.0"); + assertFalse("throw_False", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns true value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported4() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("xml", "1.0"); + assertTrue("throw_True", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns true value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported5() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("core", "2.0"); + assertTrue("throw_True", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns true value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported6() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("xml", "2.0"); + assertTrue("throw_True", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns true value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported7() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("XML", ""); + assertTrue("throw_True", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns true value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported9() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("XML", "1.0"); + assertTrue("throw_True", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns true.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported10() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("CORE", "2.0"); + assertTrue("throw_True", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns true.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported11() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("XML", "2.0"); + assertTrue("throw_True", state); + } + + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported12() throws Throwable { + List<String> features = new ArrayList<String>(); + features.add("Core"); + features.add("XML"); + features.add("HTML"); + features.add("Views"); + features.add("StyleSheets"); + features.add("CSS"); + features.add("CSS2"); + features.add("Events"); + features.add("UIEvents"); + features.add("MouseEvents"); + features.add("MutationEvents"); + features.add("HTMLEvents"); + features.add("Range"); + features.add("Traversal"); + features.add("bogus.bogus.bogus"); + + Document doc; + Node rootNode; + String featureElement; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("Core", "2.0"); + assertTrue("Core2", state); + for (int indexN10078 = 0; indexN10078 < features.size(); indexN10078++) { + featureElement = (String) features.get(indexN10078); + state = rootNode.isSupported(featureElement, "1.0"); + } + for (int indexN10083 = 0; indexN10083 < features.size(); indexN10083++) { + featureElement = (String) features.get(indexN10083); + state = rootNode.isSupported(featureElement, "2.0"); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns correct value if it has empty string as a version parameter.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported13() throws Throwable { + Document doc; + Node rootNode; + boolean state; + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("Core", ""); + assertTrue("Core", state); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns correct value if it has null as a version parameter.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported14() throws Throwable { + Document doc; + Node rootNode; + boolean state; + String nullString = null; + + doc = (Document) load("staff", builder); + rootNode = doc.getDocumentElement(); + state = rootNode.isSupported("Core", nullString); + assertTrue("Core", state); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/LocalName.java b/xml/src/test/java/tests/org/w3c/dom/LocalName.java new file mode 100644 index 0000000..3f1d9c3 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/LocalName.java @@ -0,0 +1,132 @@ +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getLocalName()" method for a Node returns the local part of the + * qualified name of this node, and for nodes of any type other than + * ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, + * this is null. + * + * Retrieve the first emp:address node and get the attributes of this node." + * Then apply the getLocalName() method to the emp:domestic attribute. The + * method should return "domestic". + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSLocalN">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSLocalN</a> + */ +@TestTargetClass(Node.class) +public final class LocalName extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "getLocalName", + args = {} + ) + public void testGetLocalName1() throws Throwable { + Document doc; + NodeList elementList; + Element testAddr; + Attr addrAttr; + String localName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + addrAttr = testAddr.getAttributeNode("emp:domestic"); + localName = addrAttr.getLocalName(); + assertEquals("localName", "domestic", localName); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that getLocalName method returns null.", + method = "getLocalName", + args = {} + ) + public void testGetLocalName2() throws Throwable { + Document doc; + Node createdNode; + String localName; + doc = (Document) load("staffNS", builder); + createdNode = doc.createElement("test:employee"); + localName = createdNode.getLocalName(); + assertNull("localNameNull", localName); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that getLocalName method returns null.", + method = "getLocalName", + args = {} + ) + public void testGetLocalName3() throws Throwable { + Document doc; + NodeList elementList; + Node testEmployee; + Node textNode; + String localName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employeeId"); + testEmployee = elementList.item(0); + textNode = testEmployee.getFirstChild(); + localName = textNode.getLocalName(); + assertNull("textNodeLocalName", localName); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "getLocalName", + args = {} + ) + public void testGetLocalName4() throws Throwable { + Document doc; + NodeList elementList; + Node testEmployee; + String employeeLocalName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + testEmployee = elementList.item(0); + employeeLocalName = testEmployee.getLocalName(); + assertEquals("lname", "employee", employeeLocalName); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapGetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapGetNamedItemNS.java new file mode 100644 index 0000000..e4ab1df --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapGetNamedItemNS.java @@ -0,0 +1,229 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; + +/** + * Using the method getNamedItemNS, retreive the entity "ent1" and notation + * "notation1" from a NamedNodeMap of this DocumentTypes entities and notations. + * Both should be null since entities and notations are not namespaced. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getNamedItemNS</a> + * @see <a + * href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a> + * @see <a + * href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=407">http://www.w3.org/Bugs/Public/show_bug.cgi?id=407</a> + * @see <a + * href="http://lists.w3.org/Archives/Member/w3c-dom-ig/2003Nov/0016.html">http://lists.w3.org/Archives/Member/w3c-dom-ig/2003Nov/0016.html</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class NamedNodeMapGetNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testGetNamedItemNS1() throws Throwable { +// Document doc; +// DocumentType docType; +// NamedNodeMap entities; +// NamedNodeMap notations; +// Entity entity; +// Notation notation; +// +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// entities = docType.getEntities(); +// assertNotNull("entitiesNotNull", entities); +// notations = docType.getNotations(); +// assertNotNull("notationsNotNull", notations); +// entity = (Entity) entities.getNamedItemNS(nullNS, "ent1"); +// assertNotNull("entityNull", entity); +// notation = (Notation) notations.getNamedItemNS(nullNS, "notation1"); +// assertNotNull("notationNull", notation); +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetNamedItemNS2() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + Attr attribute; + NodeList elementList; + String attrName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "address"); + element = elementList.item(1); + attributes = element.getAttributes(); + attribute = (Attr) attributes.getNamedItemNS("http://www.nist.gov", + "domestic"); + attrName = attribute.getNodeName(); + assertEquals("namednodemapgetnameditemns02", "emp:domestic", attrName); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetNamedItemNS3() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + Attr attribute; + Attr newAttr1; + Attr newAttr2; + + String attrName; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test", "root"); + newAttr1 = doc.createAttributeNS("http://www.w3.org/DOM/L1", "L1:att"); + ((Element) /* Node */element).setAttributeNodeNS(newAttr1); + newAttr2 = doc.createAttributeNS("http://www.w3.org/DOM/L2", "L2:att"); + ((Element) /* Node */element).setAttributeNodeNS(newAttr2); + attributes = element.getAttributes(); + attribute = (Attr) attributes.getNamedItemNS( + "http://www.w3.org/DOM/L2", "att"); + attrName = attribute.getNodeName(); + assertEquals("namednodemapgetnameditemns03", "L2:att", attrName); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetNamedItemNS4() throws Throwable { + Document doc; + NamedNodeMap attributes; + Element element; + Attr attribute; + Attr newAttr1; + NodeList elementList; + String attrName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = (Element) elementList.item(1); + newAttr1 = doc.createAttributeNS("http://www.w3.org/DOM/L1", "street"); + element.setAttributeNodeNS(newAttr1); + attributes = element.getAttributes(); + attribute = (Attr) attributes.getNamedItemNS( + "http://www.w3.org/DOM/L1", "street"); + attrName = attribute.getNodeName(); + assertEquals("namednodemapgetnameditemns04", "street", attrName); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "getNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testGetNamedItemNS5() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + Attr attribute; + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = elementList.item(1); + attributes = element.getAttributes(); + attribute = (Attr) attributes.getNamedItemNS("*", "street"); + assertNull("namednodemapgetnameditemns05", attribute); + } + +// Assumes validation. +// public void testGetNamedItemNS6() throws Throwable { +// Document doc; +// NamedNodeMap attributesMap1; +// NamedNodeMap attributesMap2; +// Element element; +// Attr attribute; +// Attr newAttr1; +// +// NodeList elementList; +// String attrName; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagNameNS("*", "address"); +// element = (Element) elementList.item(1); +// attributesMap1 = element.getAttributes(); +// attributesMap2 = element.getAttributes(); +// newAttr1 = doc.createAttributeNS("http://www.w3.org/DOM/L1", "street"); +// element.setAttributeNodeNS(newAttr1); +// attribute = (Attr) attributesMap1.getNamedItemNS( +// "http://www.w3.org/DOM/L1", "street"); +// attrName = attribute.getNodeName(); +// assertEquals("namednodemapgetnameditemnsMap106", "street", attrName); +// attribute = (Attr) attributesMap2.getNamedItemNS( +// "http://www.w3.org/DOM/L1", "street"); +// attrName = attribute.getNodeName(); +// assertEquals("namednodemapgetnameditemnsMap206", "street", attrName); +// } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapRemoveNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapRemoveNamedItemNS.java new file mode 100644 index 0000000..16a6cda --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapRemoveNamedItemNS.java @@ -0,0 +1,342 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method removeNamedItemNS removes a node specified by local name and + * namespace + * + * Retreive an attribute node and then remove from the NamedNodeMap. Verify if + * the attribute node was actually remove from the node map. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D58B193">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D58B193</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class NamedNodeMapRemoveNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS1() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + Attr attribute; + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "address"); + element = elementList.item(1); + attributes = element.getAttributes(); + attribute = (Attr) attributes.removeNamedItemNS("http://www.nist.gov", + "domestic"); + attribute = (Attr) attributes.getNamedItemNS("http://www.nist.gov", + "domestic"); + assertNull("namednodemapremovenameditemns01", attribute); + } + +// Assumes validation. +// public void testRemoveNamedItemNS2() throws Throwable { +// Document doc; +// NamedNodeMap attributes; +// Node element; +// Attr attribute; +// NodeList elementList; +// String attrValue; +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagNameNS("http://www.nist.gov", +// "employee"); +// element = elementList.item(1); +// attributes = element.getAttributes(); +// attribute = (Attr) attributes.removeNamedItemNS(nullNS, "defaultAttr"); +// attribute = (Attr) attributes.getNamedItemNS(nullNS, "defaultAttr"); +// attrValue = attribute.getNodeValue(); +// assertNotNull("namednodemapremovenameditemns02", attribute); +// assertEquals("namednodemapremovenameditemns02_attrValue", "defaultVal", +// attrValue); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS3() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + Attr attribute; + + Attr attribute1; + Attr attribute2; + String nodeName; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test", "root"); + attribute1 = doc + .createAttributeNS("http://www.w3.org/DOM/L1", "L1:att"); + ((Element) /* Node */element).setAttributeNodeNS(attribute1); + attribute2 = doc + .createAttributeNS("http://www.w3.org/DOM/L2", "L2:att"); + ((Element) /* Node */element).setAttributeNodeNS(attribute2); + attributes = element.getAttributes(); + attribute = (Attr) attributes.removeNamedItemNS( + "http://www.w3.org/DOM/L1", "att"); + attribute = (Attr) attributes.getNamedItemNS( + "http://www.w3.org/DOM/L2", "att"); + nodeName = attribute.getNodeName(); + assertEquals("namednodemapremovenameditemns02", "L2:att", nodeName); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void _testRemoveNamedItemNS4() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + Attr attribute; + + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "employee"); + element = elementList.item(0); + attributes = element.getAttributes(); + attributes.removeNamedItemNS("http://www.w3.org/2000/xmlns/", "xmlns"); + attribute = (Attr) attributes.getNamedItemNS( + "http://www.w3.org/2000/xmlns/", "xmlns"); + assertNull("namednodemapremovenameditemns04_1", attribute); + attributes.removeNamedItemNS("http://www.w3.org/2000/xmlns/", "dmstc"); + attribute = (Attr) attributes.getNamedItemNS( + "http://www.w3.org/2000/xmlns/", "dmstc"); + assertNull("namednodemapremovenameditemns04_2", attribute); + } + +// Assumes validation. +// public void testRemoveNamedItemNS5() throws Throwable { +// Document doc; +// DocumentType docType; +// NamedNodeMap entities; +// NamedNodeMap notations; +// +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// entities = docType.getEntities(); +// assertNotNull("entitiesNotNull", entities); +// notations = docType.getNotations(); +// assertNotNull("notationsNotNull", notations); +// +// try { +// entities.removeNamedItemNS(nullNS, "ent1"); +// fail("entity_throw_DOMException"); +// +// } catch (DOMException ex) { +// switch (ex.code) { +// case 8: +// break; +// case 7: +// break; +// default: +// throw ex; +// } +// } +// +// try { +// notations.removeNamedItemNS(nullNS, "notation1"); +// fail("notation_throw_DOMException"); +// +// } catch (DOMException ex) { +// switch (ex.code) { +// case 8: +// break; +// case 7: +// break; +// default: +// throw ex; +// } +// } +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that removeNamedItemNS method throws DOMException with NOT_FOUND_ERR code.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS6() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "employee"); + element = elementList.item(1); + attributes = element.getAttributes(); + + { + boolean success = false; + try { + attributes.removeNamedItemNS("http://www.Nist.gov", "domestic"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_FOUND_ERR); + } + assertTrue("throw_NOT_FOUND_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that removeNamedItemNS method throws DOMException with NOT_FOUND_ERR code.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS7() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "employee"); + element = elementList.item(1); + attributes = element.getAttributes(); + + { + boolean success = false; + try { + attributes.removeNamedItemNS("http://www.nist.gov", "domestic"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_FOUND_ERR); + } + assertTrue("throw_NOT_FOUND_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies that removeNamedItemNS method throws DOMException with NOT_FOUND_ERR code.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS8() throws Throwable { + Document doc; + NamedNodeMap attributes; + Element element; + + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "address"); + element = (Element) elementList.item(1); + attributes = element.getAttributes(); + element.removeAttributeNS("http://www.nist.gov", "domestic"); + + { + boolean success = false; + try { + attributes.removeNamedItemNS("http://www.nist.gov", "domestic"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_FOUND_ERR); + } + assertTrue("throw_NOT_FOUND_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS9() throws Throwable { + Document doc; + NamedNodeMap attributes; + NamedNodeMap newAttributes; + Element element; + Attr attribute; + NodeList elementList; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "address"); + element = (Element) elementList.item(1); + attributes = element.getAttributes(); + attribute = (Attr) attributes.removeNamedItemNS("http://www.nist.gov", + "domestic"); + newAttributes = element.getAttributes(); + attribute = (Attr) newAttributes.getNamedItemNS("http://www.nist.gov", + "domestic"); + assertNull("namednodemapremovenameditemns09", attribute); + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapSetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapSetNamedItemNS.java new file mode 100644 index 0000000..e0ec0df --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapSetNamedItemNS.java @@ -0,0 +1,451 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.Attr; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import org.w3c.dom.DOMException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.DocumentType; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method setNamedItemNS adds a node using its namespaceURI and localName. + * If a node with that namespace URI and that local name is already present in + * this map, it is replaced by the new one. + * + * Retreive the first element whose localName is address and namespaceURI + * http://www.nist.gov", and put its attributes into a named node map. Create a + * new attribute node and add it to this map. Verify if the attr node was + * successfully added by checking the nodeName of the retreived atttribute. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getNamedItemNS</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class NamedNodeMapSetNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + // Changed to configuration #2. This test case just doesn't make + // sense without a namespace-aware parser. It actually fails even + // on the JDK in that case. + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS1() throws Throwable { + Document doc; + NamedNodeMap attributes; + Node element; + Attr attribute; + + Attr newAttr1; + NodeList elementList; + String attrName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("http://www.nist.gov", + "address"); + element = elementList.item(0); + attributes = element.getAttributes(); + newAttr1 = doc.createAttributeNS("http://www.w3.org/DOM/L1", "streets"); + ((Element) /* Node */element).setAttributeNodeNS(newAttr1); + attribute = (Attr) attributes.getNamedItemNS( + "http://www.w3.org/DOM/L1", "streets"); + attrName = attribute.getNodeName(); + assertEquals("namednodemapsetnameditemns01", "streets", attrName); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS2() throws Throwable { + Document doc; + NamedNodeMap attributes; + Element element; + Attr attribute; + Attr attribute1; + + String attrName; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test", "root"); + attribute1 = doc + .createAttributeNS("http://www.w3.org/DOM/L1", "L1:att"); + attributes = element.getAttributes(); + attributes.setNamedItemNS(attribute1); + attribute = (Attr) attributes.getNamedItemNS( + "http://www.w3.org/DOM/L1", "att"); + attrName = attribute.getNodeName(); + assertEquals("namednodemapsetnameditemns02", "L1:att", attrName); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that setNamedItemNS throws DOMException with WRONG_DOCUMENT_ERR code.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS3() throws Throwable { + + Document doc; + Document docAlt; + NamedNodeMap attributes; + NamedNodeMap attributesAlt; + NodeList elementList; + NodeList elementListAlt; + Element element; + Element elementAlt; + Attr attr; + + String nullNS = null; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = (Element) elementList.item(1); + attributes = element.getAttributes(); + docAlt = (Document) load("staffNS", builder); + elementListAlt = docAlt.getElementsByTagNameNS("*", "address"); + elementAlt = (Element) elementListAlt.item(1); + attributesAlt = elementAlt.getAttributes(); + attr = (Attr) attributesAlt.getNamedItemNS(nullNS, "street"); + attributesAlt.removeNamedItemNS(nullNS, "street"); + + { + boolean success = false; + try { + attributes.setNamedItemNS(attr); + } catch (DOMException ex) { + success = (ex.code == DOMException.WRONG_DOCUMENT_ERR); + } + assertTrue("throw_WRONG_DOCUMENT_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that setNamedItemNS throws DOMException with WRONG_DOCUMENT_ERR code.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS4() throws Throwable { + Document doc; + DOMImplementation domImpl; + Document docAlt; + DocumentType docType = null; + + NamedNodeMap attributes; + NodeList elementList; + Element element; + Attr attrAlt; + + String nullNS = null; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = (Element) elementList.item(1); + attributes = element.getAttributes(); + domImpl = doc.getImplementation(); + docAlt = domImpl.createDocument(nullNS, "newDoc", docType); + attrAlt = docAlt.createAttributeNS(nullNS, "street"); + + { + boolean success = false; + try { + attributes.setNamedItemNS(attrAlt); + } catch (DOMException ex) { + success = (ex.code == DOMException.WRONG_DOCUMENT_ERR); + } + assertTrue("throw_WRONG_DOCUMENT_ERR", success); + } + } + +// Assumes validation. +// public void testSetNamedItemNS5() throws Throwable { +// Document doc; +// DocumentType docType; +// NamedNodeMap entities; +// NamedNodeMap notations; +// Entity entity; +// Notation notation; +// +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// entities = docType.getEntities(); +// assertNotNull("entitiesNotNull", entities); +// notations = docType.getNotations(); +// assertNotNull("notationsNotNull", notations); +// entity = (Entity) entities.getNamedItem("ent1"); +// notation = (Notation) notations.getNamedItem("notation1"); +// +// { +// boolean success = false; +// try { +// entities.setNamedItemNS(entity); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR_entities", success); +// } +// +// { +// boolean success = false; +// try { +// notations.setNamedItemNS(notation); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR_notations", success); +// } +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that setNamedItemNS throws DOMException with INUSE_ATTRIBUTE_ERR code.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS6() throws Throwable { + Document doc; + NamedNodeMap attributes; + NodeList elementList; + Element element; + Attr attr; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = (Element) elementList.item(0); + attributes = element.getAttributes(); + attr = (Attr) attributes.getNamedItemNS("http://www.usa.com", + "domestic"); + element = (Element) elementList.item(1); + attributes = element.getAttributes(); + + { + boolean success = false; + try { + attributes.setNamedItemNS(attr); + } catch (DOMException ex) { + success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR); + } + assertTrue("namednodemapsetnameditemns06", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that setNamedItemNS throws DOMException with INUSE_ATTRIBUTE_ERR code.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS7() throws Throwable { + Document doc; + NamedNodeMap attributes; + NodeList elementList; + Element element; + Attr attr; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = (Element) elementList.item(0); + attributes = element.getAttributes(); + attr = (Attr) attributes.getNamedItemNS("http://www.usa.com", + "domestic"); + element = (Element) elementList.item(1); + attributes = element.getAttributes(); + + { + boolean success = false; + try { + attributes.setNamedItemNS(attr); + } catch (DOMException ex) { + success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR); + } + assertTrue("namednodemapsetnameditemns07", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that setNamedItemNS throws DOMException with INUSE_ATTRIBUTE_ERR code.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS8() throws Throwable { + Document doc; + NamedNodeMap attributes; + NodeList elementList; + Element element; + Attr attr; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagNameNS("*", "address"); + element = (Element) elementList.item(0); + attributes = element.getAttributes(); + attr = (Attr) attributes.getNamedItemNS("http://www.usa.com", + "domestic"); + element = (Element) elementList.item(1); + attributes = element.getAttributes(); + + { + boolean success = false; + try { + attributes.setNamedItemNS(attr); + } catch (DOMException ex) { + success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR); + } + assertTrue("namednodemapsetnameditemns08", success); + } + } + +// Assumes validation. +// public void testSetNamedItemNS9() throws Throwable { +// Document doc; +// DocumentType docType; +// NamedNodeMap entities; +// NamedNodeMap notations; +// Attr attr; +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// entities = docType.getEntities(); +// notations = docType.getNotations(); +// attr = doc.createAttributeNS("http://www.w3.org/DOM/Test", "test"); +// +// { +// boolean success = false; +// try { +// entities.setNamedItemNS(attr); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR_entities", success); +// } +// +// { +// boolean success = false; +// try { +// notations.setNamedItemNS(attr); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR_notations", success); +// } +// } + +// Assumes validation. +// public void testSetNamedItemNS10() throws Throwable { +// Document doc; +// DocumentType docType; +// NamedNodeMap entities; +// NamedNodeMap attributes; +// Entity entity; +// +// Element element; +// NodeList elementList; +// +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// entities = docType.getEntities(); +// assertNotNull("entitiesNotNull", entities); +// entity = (Entity) entities.getNamedItem("ent1"); +// elementList = doc.getElementsByTagNameNS("http://www.nist.gov", +// "address"); +// element = (Element) elementList.item(0); +// attributes = element.getAttributes(); +// +// { +// boolean success = false; +// try { +// attributes.setNamedItemNS(entity); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.HIERARCHY_REQUEST_ERR); +// } +// assertTrue("throw_HIERARCHY_REQUEST_ERR", success); +// } +// } + +// Assumes validation. +// public void testSetNamedItemNS11() throws Throwable { +// Document doc; +// DocumentType docType; +// NamedNodeMap notations; +// NamedNodeMap attributes; +// Notation notation; +// Element element; +// NodeList elementList; +// +// doc = (Document) load("staffNS", builder); +// docType = doc.getDoctype(); +// notations = docType.getNotations(); +// assertNotNull("notationsNotNull", notations); +// notation = (Notation) notations.getNamedItem("notation1"); +// elementList = doc.getElementsByTagNameNS("http://www.nist.gov", +// "address"); +// element = (Element) elementList.item(0); +// attributes = element.getAttributes(); +// +// { +// boolean success = false; +// try { +// attributes.setNamedItemNS(notation); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.HIERARCHY_REQUEST_ERR); +// } +// assertTrue("throw_HIERARCHY_REQUEST_ERR", success); +// } +// } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NamespaceURI.java b/xml/src/test/java/tests/org/w3c/dom/NamespaceURI.java new file mode 100644 index 0000000..dba8b86 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NamespaceURI.java @@ -0,0 +1,153 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2003 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getNamespaceURI()" method for an Attribute returns the namespace URI of + * this node, or null if unspecified. + * + * Retrieve the first "emp:address" node which has an attribute of + * "emp:district" that is specified in the DTD. Invoke the "getNamespaceURI()" + * method on the attribute. The method should return "http://www.nist.gov". + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSname">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSname</a> + * @see <a + * href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=238">http://www.w3.org/Bugs/Public/show_bug.cgi?id=238</a> + */ +@TestTargetClass(Attr.class) +public final class NamespaceURI extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testGetNamespaceURI1() throws Throwable { +// Document doc; +// NodeList elementList; +// Element testAddr; +// Attr addrAttr; +// String attrNamespaceURI; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("emp:address"); +// testAddr = (Element) elementList.item(0); +// addrAttr = testAddr.getAttributeNodeNS("http://www.nist.gov", +// "district"); +// attrNamespaceURI = addrAttr.getNamespaceURI(); +// assertEquals("namespaceURI", "http://www.nist.gov", attrNamespaceURI); +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify that getNamespaceURI method returns null.", + method = "getNamespaceURI", + args = {} + ) + public void testGetNamespaceURI2() throws Throwable { + Document doc; + NodeList elementList; + Element testAddr; + Attr addrAttr; + String attrNamespaceURI; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = (Element) elementList.item(0); + assertNotNull("empAddressNotNull", testAddr); + addrAttr = testAddr.getAttributeNodeNS("http://www.nist.gov", + "domestic"); + attrNamespaceURI = addrAttr.getNamespaceURI(); + assertEquals("namespaceURI", "http://www.nist.gov", attrNamespaceURI); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify that getNamespaceURI method returns null.", + method = "getNamespaceURI", + args = {} + ) + public void testGetNamespaceURI3() throws Throwable { + Document doc; + NodeList elementList; + Node testEmployee; + String employeeNamespace; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + testEmployee = elementList.item(0); + assertNotNull("employeeNotNull", testEmployee); + employeeNamespace = testEmployee.getNamespaceURI(); + assertEquals("namespaceURI", "http://www.nist.gov", employeeNamespace); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getNamespaceURI method returns null.", + method = "getNamespaceURI", + args = {} + ) + public void testGetNamespaceURI4() throws Throwable { + Document doc; + NodeList elementList; + Node testEmployee; + String employeeNamespace; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + testEmployee = elementList.item(1); + employeeNamespace = testEmployee.getNamespaceURI(); + assertNull("throw_Null", employeeNamespace); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeGetLocalName.java b/xml/src/test/java/tests/org/w3c/dom/NodeGetLocalName.java new file mode 100644 index 0000000..d508465 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NodeGetLocalName.java @@ -0,0 +1,107 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getLocalName returns the local part of the qualified name of this node. + * + * Ceate two new element nodes and atribute nodes, with and without namespace prefixes. + * Retreive the local part of their qualified names using getLocalName and verrify + * if it is correct. +* @author IBM +* @author Neil Delima +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSLocalN">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSLocalN</a> +*/ +@TestTargetClass(Node.class) +public final class NodeGetLocalName extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify that getLocalName method returns null.", + method = "getLocalName", + args = {} + ) + public void testGetLocalName() throws Throwable { + Document doc; + Element element; + Element qelement; + Attr attr; + Attr qattr; + String localElemName; + String localQElemName; + String localAttrName; + String localQAttrName; + doc = (Document) load("staff", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "elem"); + qelement = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "qual:qelem"); + attr = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "attr"); + qattr = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "qual:qattr"); + localElemName = element.getLocalName(); + localQElemName = qelement.getLocalName(); + localAttrName = attr.getLocalName(); + localQAttrName = qattr.getLocalName(); + assertEquals("nodegetlocalname03_localElemName", "elem", localElemName); + assertEquals("nodegetlocalname03_localQElemName", "qelem", localQElemName); + assertEquals("nodegetlocalname03_localAttrName", "attr", localAttrName); + assertEquals("nodegetlocalname03_localQAttrName", "qattr", localQAttrName); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeGetNamespaceURI.java b/xml/src/test/java/tests/org/w3c/dom/NodeGetNamespaceURI.java new file mode 100644 index 0000000..5ed1e29 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NodeGetNamespaceURI.java @@ -0,0 +1,111 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001-2003 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getNamespaceURI returns the namespace URI of this node, or null if it is unspecified + * For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with + * a DOM Level 1 method, such as createElement from the Document interface, this is always null. + * + * Ceate two new element nodes and atribute nodes, with and without namespace prefixes. + * Retreive their namespaceURI's using getNamespaceURI and verrify if it is correct. +* @author IBM +* @author Neil Delima +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSname">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSname</a> +* @see <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a> +*/ +@TestTargetClass(Node.class) +public final class NodeGetNamespaceURI extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getNamespaceURI", + args = {} + ) + public void testGetNamespaceURI() throws Throwable { + Document doc; + Element element; + Element elementNS; + Attr attr; + Attr attrNS; + String elemNSURI; + String elemNSURINull; + String attrNSURI; + String attrNSURINull; + String nullNS = null; + + doc = (Document) load("staff", builder); + element = doc.createElementNS(nullNS, "elem"); + elementNS = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "qual:qelem"); + attr = doc.createAttributeNS(nullNS, "attr"); + attrNS = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "qual:qattr"); + elemNSURI = elementNS.getNamespaceURI(); + elemNSURINull = element.getNamespaceURI(); + attrNSURI = attrNS.getNamespaceURI(); + attrNSURINull = attr.getNamespaceURI(); + assertEquals("nodegetnamespaceuri03_elemNSURI", "http://www.w3.org/DOM/Test/elem", elemNSURI); + assertNull("nodegetnamespaceuri03_1", elemNSURINull); + assertEquals("nodegetnamespaceuri03_attrNSURI", "http://www.w3.org/DOM/Test/attr", attrNSURI); + assertNull("nodegetnamespaceuri03_2", attrNSURINull); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeGetOwnerDocument.java b/xml/src/test/java/tests/org/w3c/dom/NodeGetOwnerDocument.java new file mode 100644 index 0000000..3579c15 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NodeGetOwnerDocument.java @@ -0,0 +1,128 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2003 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getOwnerDocument returns the Document object associated with this + * node + * + * Create a new DocumentType node. Since this node is not used with any Document + * yet verify if the ownerDocument is null. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#node-ownerDoc">http://www.w3.org/TR/DOM-Level-2-Core/core#node-ownerDoc</a> + * @see <a + * href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a> + */ +@TestTargetClass(Node.class) +public final class NodeGetOwnerDocument extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getOwnerDocument method returns null.", + method = "getOwnerDocument", + args = {} + ) + public void testGetOwnerDocument1() throws Throwable { + Document doc; + Document ownerDoc; + DOMImplementation domImpl; + DocumentType docType; + String nullID = null; + + doc = (Document) load("staff", builder); + domImpl = doc.getImplementation(); + docType = domImpl.createDocumentType("mydoc", nullID, nullID); + ownerDoc = docType.getOwnerDocument(); + assertNull("nodegetownerdocument01", ownerDoc); + } + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getOwnerDocument", + args = {} + ) + public void testGetOwnerDocument2() throws Throwable { + Document doc; + Document newDoc; + Element newElem; + Document ownerDocDoc; + Document ownerDocElem; + DOMImplementation domImpl; + DocumentType docType; + String nullNS = null; + + doc = (Document) load("staff", builder); + domImpl = doc.getImplementation(); + docType = domImpl.createDocumentType("mydoc", nullNS, nullNS); + newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", "mydoc", + docType); + ownerDocDoc = newDoc.getOwnerDocument(); + assertNull("nodegetownerdocument02_1", ownerDocDoc); + newElem = newDoc + .createElementNS("http://www.w3.org/DOM/Test", "myelem"); + ownerDocElem = newElem.getOwnerDocument(); + assertNotNull("nodegetownerdocument02_2", ownerDocElem); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeGetPrefix.java b/xml/src/test/java/tests/org/w3c/dom/NodeGetPrefix.java new file mode 100644 index 0000000..bcf8bba --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NodeGetPrefix.java @@ -0,0 +1,108 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method getPrefix returns the namespace prefix of this node, or null if it is unspecified. + * + * Ceate two new element nodes and atribute nodes, with and without namespace prefixes. + * Retreive the prefix part of their qualified names using getPrefix and verify + * if it is correct. +* @author IBM +* @author Neil Delima +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix</a> +*/ +@TestTargetClass(Node.class) +public final class NodeGetPrefix extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getPrefix", + args = {} + ) + public void testGetPrefix() throws Throwable { + Document doc; + Element element; + Element qelement; + Attr attr; + Attr qattr; + String elemNoPrefix; + String elemPrefix; + String attrNoPrefix; + String attrPrefix; + doc = (Document) load("staff", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "elem"); + qelement = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "qual:qelem"); + attr = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "attr"); + qattr = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "qual:qattr"); + elemNoPrefix = element.getPrefix(); + elemPrefix = qelement.getPrefix(); + attrNoPrefix = attr.getPrefix(); + attrPrefix = qattr.getPrefix(); + assertNull("nodegetprefix03_1", elemNoPrefix); + assertEquals("nodegetprefix03_2", "qual", elemPrefix); + assertNull("nodegetprefix03_3", attrNoPrefix); + assertEquals("nodegetprefix03_4", "qual", attrPrefix); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeHasAttributes.java b/xml/src/test/java/tests/org/w3c/dom/NodeHasAttributes.java new file mode 100644 index 0000000..514b205 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NodeHasAttributes.java @@ -0,0 +1,171 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Attr; +import org.w3c.dom.DOMImplementation; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method hasAttributes returns whether this node (if it is an element) has + * any attributes. Retreive an element node without attributes. Verify if + * hasAttributes returns false. Retreive another element node with attributes. + * Verify if hasAttributes returns true. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs</a> + */ +@TestTargetClass(Node.class) +public final class NodeHasAttributes extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "hasAttributes", + args = {} + ) + public void testHasAttributes1() throws Throwable { + Document doc; + Element element; + NodeList elementList; + boolean hasAttributes; + doc = (Document) load("staff", builder); + elementList = doc.getElementsByTagName("employee"); + element = (Element) elementList.item(0); + hasAttributes = element.hasAttributes(); + assertFalse("nodehasattributes01_1", hasAttributes); + elementList = doc.getElementsByTagName("address"); + element = (Element) elementList.item(0); + hasAttributes = element.hasAttributes(); + assertTrue("nodehasattributes01_2", hasAttributes); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that hasAttributes method returns false value.", + method = "hasAttributes", + args = {} + ) + public void testHasAttributes2() throws Throwable { + Document doc; + DocumentType docType; + boolean hasAttributes; + doc = (Document) load("staffNS", builder); + docType = doc.getDoctype(); + hasAttributes = docType.hasAttributes(); + assertFalse("nodehasattributes02", hasAttributes); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that hasAttributes method returns true value.", + method = "hasAttributes", + args = {} + ) + public void testHasAttributes3() throws Throwable { + Document doc; + Element element; + NodeList elementList; + boolean hasAttributes; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:employee"); + element = (Element) elementList.item(0); + assertNotNull("empEmployeeNotNull", element); + hasAttributes = element.hasAttributes(); + assertTrue("hasAttributes", hasAttributes); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that hasAttributes method returns true value.", + method = "hasAttributes", + args = {} + ) + public void testHasAttributes4() throws Throwable { + Document doc; + Document newDoc; + DocumentType docType = null; + + DOMImplementation domImpl; + Element element; + Element elementTest; + Element elementDoc; + Attr attribute; + + + NodeList elementList; + boolean hasAttributes; + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", "test", + docType); + element = newDoc.createElementNS("http://www.w3.org/DOM/Test", + "dom:elem"); + attribute = newDoc.createAttribute("attr"); + element.setAttributeNode(attribute); + elementDoc = newDoc.getDocumentElement(); + elementDoc.appendChild(element); + elementList = newDoc.getElementsByTagNameNS( + "http://www.w3.org/DOM/Test", "elem"); + elementTest = (Element) elementList.item(0); + hasAttributes = elementTest.hasAttributes(); + assertTrue("nodehasattributes04", hasAttributes); + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeIsSupported.java b/xml/src/test/java/tests/org/w3c/dom/NodeIsSupported.java new file mode 100644 index 0000000..d88cb86 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NodeIsSupported.java @@ -0,0 +1,216 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2003 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Attr; +import org.w3c.dom.DocumentType; +import org.w3c.dom.EntityReference; +import org.w3c.dom.ProcessingInstruction; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method "isSupported(feature,version)" Tests whether the DOM + * implementation implements a specific feature and that feature is supported by + * this node. + * + * Call the isSupported method on the document element node with a combination + * of features versions and versions as below. Valid feature names are case + * insensitive and versions "2.0", "1.0" and if the version is not specified, + * supporting any version of the feature should return true. Check if the value + * returned value was true. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-Node-supports">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-Node-supports</a> + */ +@TestTargetClass(Node.class) +public final class NodeIsSupported extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify that isSupported method can return false value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported1() throws Throwable { + Document doc; + Element element; + String version = ""; + String version1 = "1.0"; + String version2 = "2.0"; + String featureCore; + String featureXML; + boolean success; + List<String> featuresXML = new ArrayList<String>(); + featuresXML.add("XML"); + featuresXML.add("xmL"); + + List<String> featuresCore = new ArrayList<String>(); + featuresCore.add("Core"); + featuresCore.add("CORE"); + + doc = (Document) load("staffNS", builder); + element = doc.getDocumentElement(); + for (int indexN10063 = 0; indexN10063 < featuresXML.size(); indexN10063++) { + featureXML = (String) featuresXML.get(indexN10063); + success = element.isSupported(featureXML, version); + assertTrue("nodeissupported01_XML1", success); + success = element.isSupported(featureXML, version1); + assertTrue("nodeissupported01_XML2", success); + } + for (int indexN1007C = 0; indexN1007C < featuresCore.size(); indexN1007C++) { + featureCore = (String) featuresCore.get(indexN1007C); + success = element.isSupported(featureCore, version); + assertTrue("nodeissupported01_Core1", success); + success = element.isSupported(featureCore, version1); + success = element.isSupported(featureCore, version2); + assertTrue("nodeissupported01_Core3", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify that isSupported method can return false value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported2() throws Throwable { + Document doc; + Attr attribute; + String version = ""; + String version1 = "1.0"; + String version2 = "2.0"; + String featureCore; + String featureXML; + boolean success; + List<String> featuresXML = new ArrayList<String>(); + featuresXML.add("XML"); + featuresXML.add("xmL"); + + List<String> featuresCore = new ArrayList<String>(); + featuresCore.add("Core"); + featuresCore.add("CORE"); + + doc = (Document) load("staffNS", builder); + attribute = doc.createAttribute("TestAttr"); + for (int indexN10064 = 0; indexN10064 < featuresXML.size(); indexN10064++) { + featureXML = (String) featuresXML.get(indexN10064); + success = attribute.isSupported(featureXML, version); + assertTrue("nodeissupported02_XML1", success); + success = attribute.isSupported(featureXML, version1); + assertTrue("nodeissupported02_XML2", success); + } + for (int indexN1007D = 0; indexN1007D < featuresCore.size(); indexN1007D++) { + featureCore = (String) featuresCore.get(indexN1007D); + success = attribute.isSupported(featureCore, version); + assertTrue("nodeissupported02_Core1", success); + success = attribute.isSupported(featureCore, version1); + success = attribute.isSupported(featureCore, version2); + assertTrue("nodeissupported02_Core3", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns false value if it's called with empty strings as parameters.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported3() throws Throwable { + Document doc; + DocumentType docType; + boolean success; + doc = (Document) load("staffNS", builder); + docType = doc.getDoctype(); + success = docType.isSupported("", ""); + assertFalse("nodeissupported03", success); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns false value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported4() throws Throwable { + Document doc; + EntityReference entRef; + boolean success; + doc = (Document) load("staffNS", builder); + entRef = doc.createEntityReference("ent1"); + assertNotNull("createdEntRefNotNull", entRef); + success = entRef.isSupported("XML CORE", ""); + assertFalse("nodeissupported04", success); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that isSupported method returns false value.", + method = "isSupported", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testIsSupported5() throws Throwable { + Document doc; + ProcessingInstruction pi; + boolean success; + doc = (Document) load("staffNS", builder); + pi = doc.createProcessingInstruction("PITarget", "PIData"); + success = pi.isSupported("-", "+"); + assertFalse("nodeissupported05", success); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeNormalize.java b/xml/src/test/java/tests/org/w3c/dom/NodeNormalize.java new file mode 100644 index 0000000..d66ce58 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NodeNormalize.java @@ -0,0 +1,209 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Text; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.EntityReference; +import org.w3c.dom.NodeList; +import org.w3c.dom.CDATASection; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Comment; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method "normalize" puts all Text nodes in the full depth of the sub-tree + * underneath this Node, including attribute nodes, into a "normal" form where + * only structure (e.g., elements, comments, processing instructions, CDATA + * sections, and entity references) separates Text nodes, i.e., there are + * neither adjacent Text nodes nor empty Text nodes. + * + * Create a dom tree consisting of elements, comments, processing instructions, + * CDATA sections, and entity references nodes seperated by text nodes. Check + * the length of the node list of each before and after normalize has been + * called. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-normalize">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-normalize</a> + */ +@TestTargetClass(Node.class) +public final class NodeNormalize extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "normalize", + args = {} + ) + public void testNormalize() throws Throwable { + Document doc; + Document newDoc; + DOMImplementation domImpl; + + DocumentType docTypeNull = null; + + Element documentElement; + Element element1; + Element element2; + Element element3; + Element element4; + Element element5; + Element element6; + Element element7; + Text text1; + Text text2; + Text text3; + ProcessingInstruction pi; + CDATASection cData; + Comment comment; + EntityReference entRef; + NodeList elementList; + + doc = (Document) load("staffNS", builder); + domImpl = doc.getImplementation(); + newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", + "dom:root", docTypeNull); + element1 = newDoc.createElement("element1"); + element2 = newDoc.createElement("element2"); + element3 = newDoc.createElement("element3"); + element4 = newDoc.createElement("element4"); + element5 = newDoc.createElement("element5"); + element6 = newDoc.createElement("element6"); + element7 = newDoc.createElement("element7"); + text1 = newDoc.createTextNode("text1"); + text2 = newDoc.createTextNode("text2"); + text3 = newDoc.createTextNode("text3"); + cData = newDoc.createCDATASection("Cdata"); + comment = newDoc.createComment("comment"); + pi = newDoc.createProcessingInstruction("PITarget", "PIData"); + entRef = newDoc.createEntityReference("EntRef"); + assertNotNull("createdEntRefNotNull", entRef); + documentElement = newDoc.getDocumentElement(); + documentElement.appendChild(element1); + element2.appendChild(text1); + element2.appendChild(text2); + element2.appendChild(text3); + element1.appendChild(element2); + text1 = (Text) text1.cloneNode(false); + text2 = (Text) text2.cloneNode(false); + element3.appendChild(entRef); + element3.appendChild(text1); + element3.appendChild(text2); + element1.appendChild(element3); + text1 = (Text) text1.cloneNode(false); + text2 = (Text) text2.cloneNode(false); + element4.appendChild(cData); + element4.appendChild(text1); + element4.appendChild(text2); + element1.appendChild(element4); + text2 = (Text) text2.cloneNode(false); + text3 = (Text) text3.cloneNode(false); + element5.appendChild(comment); + element5.appendChild(text2); + element5.appendChild(text3); + element1.appendChild(element5); + text2 = (Text) text2.cloneNode(false); + text3 = (Text) text3.cloneNode(false); + element6.appendChild(pi); + element6.appendChild(text2); + element6.appendChild(text3); + element1.appendChild(element6); + entRef = (EntityReference) entRef.cloneNode(false); + text1 = (Text) text1.cloneNode(false); + text2 = (Text) text2.cloneNode(false); + text3 = (Text) text3.cloneNode(false); + element7.appendChild(entRef); + element7.appendChild(text1); + element7.appendChild(text2); + element7.appendChild(text3); + element1.appendChild(element7); + elementList = element1.getChildNodes(); + assertEquals("nodeNormalize01_1Bef", 6, elementList.getLength()); + elementList = element2.getChildNodes(); + assertEquals("nodeNormalize01_2Bef", 3, elementList.getLength()); + elementList = element3.getChildNodes(); + assertEquals("nodeNormalize01_3Bef", 3, elementList.getLength()); + elementList = element4.getChildNodes(); + assertEquals("nodeNormalize01_4Bef", 3, elementList.getLength()); + elementList = element5.getChildNodes(); + assertEquals("nodeNormalize01_5Bef", 3, elementList.getLength()); + elementList = element6.getChildNodes(); + assertEquals("nodeNormalize01_6Bef", 3, elementList.getLength()); + elementList = element7.getChildNodes(); + assertEquals("nodeNormalize01_7Bef", 4, elementList.getLength()); + newDoc.normalize(); + elementList = element1.getChildNodes(); + assertEquals("nodeNormalize01_1Aft", 6, elementList.getLength()); + elementList = element2.getChildNodes(); + assertEquals("nodeNormalize01_2Aft", 1, elementList.getLength()); + elementList = element3.getChildNodes(); + assertEquals("nodeNormalize01_3Aft", 2, elementList.getLength()); + elementList = element4.getChildNodes(); + assertEquals("nodeNormalize01_4Aft", 2, elementList.getLength()); + elementList = element5.getChildNodes(); + assertEquals("nodeNormalize01_5Aft", 2, elementList.getLength()); + elementList = element6.getChildNodes(); + assertEquals("nodeNormalize01_6Aft", 2, elementList.getLength()); + elementList = element7.getChildNodes(); + assertEquals("nodeNormalize01_7Aft", 2, elementList.getLength()); + } + +} diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeSetPrefix.java b/xml/src/test/java/tests/org/w3c/dom/NodeSetPrefix.java new file mode 100644 index 0000000..dbecc30 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/NodeSetPrefix.java @@ -0,0 +1,314 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Element; +import org.w3c.dom.DOMException; +import org.w3c.dom.Attr; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The method setPrefix sets the namespace prefix of this node. Note that + * setting this attribute, when permitted, changes the nodeName attribute, which + * holds the qualified name, as well as the tagName and name attributes of the + * Element and Attr interfaces, when applicable. + * + * Create a new element node with a namespace prefix. Add it to a new + * DocumentFragment Node without a prefix. Call setPrefix on the elemen node. + * Check if the prefix was set correctly on the element. + * + * @author IBM + * @author Neil Delima + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix</a> + */ +@TestTargetClass(Node.class) +public final class NodeSetPrefix extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "setPrefix", + args = {java.lang.String.class} + ) + public void testSetPrefix1() throws Throwable { + Document doc; + DocumentFragment docFragment; + Element element; + String elementTagName; + String elementNodeName; + + doc = (Document) load("staff", builder); + docFragment = doc.createDocumentFragment(); + element = doc.createElementNS("http://www.w3.org/DOM/Test", + "emp:address"); + docFragment.appendChild(element); + element.setPrefix("dmstc"); + elementTagName = element.getTagName(); + elementNodeName = element.getNodeName(); + assertEquals("nodesetprefix01_tagname", "dmstc:address", elementTagName); + assertEquals("nodesetprefix01_nodeName", "dmstc:address", + elementNodeName); + } + +// TODO Fails on JDK. Why? +// public void testSetPrefix2() throws Throwable { +// Document doc; +// Element element; +// Attr attribute; +// Attr newAttribute; +// +// NodeList elementList; +// String attrName; +// String newAttrName; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("address"); +// element = (Element) elementList.item(1); +// newAttribute = doc.createAttributeNS("http://www.w3.org/DOM/Test", +// "test:address"); +// element.setAttributeNodeNS(newAttribute); +// newAttribute.setPrefix("dom"); +// attribute = element +// .getAttributeNodeNS("http://www.usa.com", "domestic"); +// attrName = attribute.getNodeName(); +// newAttrName = newAttribute.getNodeName(); +// assertEquals("nodesetprefix02_attrName", "dmstc:domestic", attrName); +// assertEquals("nodesetprefix02_newAttrName", "dom:address", newAttrName); +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setPrefix", + args = {java.lang.String.class} + ) + public void testSetPrefix3() throws Throwable { + Document doc; + Element element; + doc = (Document) load("staffNS", builder); + element = doc.createElement("address"); + + { + boolean success = false; + try { + element.setPrefix("test"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + +// Relies on validation, which we don't support. +// public void testSetPrefix4() throws Throwable { +// Document doc; +// Element element; +// Attr attribute; +// NodeList elementList; +// String nullNS = null; +// +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("emp:employee"); +// element = (Element) elementList.item(0); +// assertNotNull("empEmployeeNotNull", element); +// attribute = element.getAttributeNodeNS(nullNS, "defaultAttr"); +// +// { +// boolean success = false; +// try { +// attribute.setPrefix("test"); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NAMESPACE_ERR); +// } +// assertTrue("nodesetprefix04", success); +// } +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setPrefix", + args = {java.lang.String.class} + ) + public void testSetPrefix5() throws Throwable { + Document doc; + Element element; + String prefixValue; + List<String> prefixValues = new ArrayList<String>(); + prefixValues.add("_:"); + prefixValues.add(":0"); + prefixValues.add(":"); + prefixValues.add("_::"); + prefixValues.add("a:0:c"); + + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test/L2", + "dom:elem"); + for (int indexN10050 = 0; indexN10050 < prefixValues.size(); indexN10050++) { + prefixValue = (String) prefixValues.get(indexN10050); + + { + boolean success = false; + try { + element.setPrefix(prefixValue); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setPrefix", + args = {java.lang.String.class} + ) + public void testSetPrefix6() throws Throwable { + Document doc; + Element element; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test/L2", + "dom:elem"); + + { + boolean success = false; + try { + element.setPrefix("xml"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setPrefix", + args = {java.lang.String.class} + ) + public void testSetPrefix7() throws Throwable { + Document doc; + Attr attribute; + doc = (Document) load("staffNS", builder); + attribute = doc.createAttributeNS("http://www.w3.org/DOM/Test/L2", + "abc:elem"); + + { + boolean success = false; + try { + attribute.setPrefix("xmlns"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR.", + method = "setPrefix", + args = {java.lang.String.class} + ) + public void testSetPrefix8() throws Throwable { + Document doc; + Element element; + NodeList elementList; + Attr attribute; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + element = (Element) elementList.item(0); + attribute = element.getAttributeNode("xmlns"); + + { + boolean success = false; + try { + attribute.setPrefix("xml"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with INVALID_CHARACTER_ERR code.", + method = "setPrefix", + args = {java.lang.String.class} + ) + public void _testSetPrefix9() throws Throwable { + Document doc; + String value = "#$%&'()@"; + Element element; + doc = (Document) load("staffNS", builder); + element = doc.createElementNS("http://www.w3.org/DOM/Test/L2", + "dom:elem"); + + { + boolean success = false; + try { + element.setPrefix(value); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("throw_INVALID_CHARACTER_ERR", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/Normalize.java b/xml/src/test/java/tests/org/w3c/dom/Normalize.java new file mode 100644 index 0000000..36ff43c --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/Normalize.java @@ -0,0 +1,106 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.CharacterData; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "normalize()" method puts all the nodes in the full + * depth of the sub-tree underneath this element into a + * "normal" form. + * + * Retrieve the third employee and access its second child. + * This child contains a block of text that is spread + * across multiple lines. The content of the "name" child + * should be parsed and treated as a single Text node. + * This appears to be a duplicate of elementnormalize.xml in DOM L1 Test Suite +* @author NIST +* @author Mary Brady +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-normalize">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-normalize</a> +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-72AB8359">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-72AB8359</a> +*/ +@TestTargetClass(Element.class) +public final class Normalize extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "normalize", + args = {} + ) + public void testNormalize() throws Throwable { + Document doc; + Element root; + NodeList elementList; + Node firstChild; + NodeList textList; + CharacterData textNode; + String data; + doc = (Document) load("staff", builder); + root = doc.getDocumentElement(); + root.normalize(); + elementList = root.getElementsByTagName("name"); + firstChild = elementList.item(2); + textList = firstChild.getChildNodes(); + textNode = (CharacterData) textList.item(0); + data = textNode.getData(); + assertEquals("data", "Roger\n Jones", data); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/OwnerDocument.java b/xml/src/test/java/tests/org/w3c/dom/OwnerDocument.java new file mode 100644 index 0000000..b5b0e94 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/OwnerDocument.java @@ -0,0 +1,88 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getOwnerDocument()" method returns null if the target + * node itself is a DocumentType which is not used with any document yet. + * + * Invoke the "getOwnerDocument()" method on the master + * document. The DocumentType returned should be null. +* @author NIST +* @author Mary Brady +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#node-ownerDoc">http://www.w3.org/TR/DOM-Level-2-Core/core#node-ownerDoc</a> +*/ +@TestTargetClass(Document.class) +public final class OwnerDocument extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Dosn't verify that getOwnerDocument can return not null value.", + method = "getOwnerDocument", + args = {} + ) + public void testGetOwnerDocument() throws Throwable { + Document doc; + DocumentType ownerDocument; + doc = (Document) load("staff", builder); + ownerDocument = (DocumentType) doc.getOwnerDocument(); + assertNull("throw_Null", ownerDocument); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/OwnerElement.java b/xml/src/test/java/tests/org/w3c/dom/OwnerElement.java new file mode 100644 index 0000000..a4af36a --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/OwnerElement.java @@ -0,0 +1,118 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getOwnerElement()" will return the Element node this attribute is + * attached to or null if this attribute is not in use. Get the "domestic" + * attribute from the first "address" node. Apply the "getOwnerElement()" method + * to get the Element associated with the attribute. The value returned should + * be "address". + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095</a> + */ +@TestTargetClass(Attr.class) +public final class OwnerElement extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies positive functionlity.", + method = "getOwnerElement", + args = {} + ) + public void testGetOwnerElement1() throws Throwable { + Document doc; + NodeList addressList; + Node testNode; + NamedNodeMap attributes; + Attr domesticAttr; + Element elementNode; + String name; + doc = (Document) load("staff", builder); + addressList = doc.getElementsByTagName("address"); + testNode = addressList.item(0); + attributes = testNode.getAttributes(); + domesticAttr = (Attr) attributes.getNamedItem("domestic"); + elementNode = domesticAttr.getOwnerElement(); + name = elementNode.getNodeName(); + assertEquals("throw_Equals", "address", name); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getOwnerElement method returns null.", + method = "getOwnerElement", + args = {} + ) + public void testGetOwnerElement2() throws Throwable { + Document doc; + Attr newAttr; + Element elementNode; + doc = (Document) load("staff", builder); + newAttr = doc.createAttribute("newAttribute"); + elementNode = newAttr.getOwnerElement(); + assertNull("throw_Null", elementNode); + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/Prefix.java b/xml/src/test/java/tests/org/w3c/dom/Prefix.java new file mode 100644 index 0000000..f45144a --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/Prefix.java @@ -0,0 +1,337 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getPrefix()" method for a Node returns the namespace prefix of the node, + * and for nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and + * nodes created with a DOM Level 1 method, this is null. + * + * Create an new Element with the createElement() method. Invoke the + * "getPrefix()" method on the newly created element node will cause "null" to + * be returned. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix</a> + */ +@TestTargetClass(Node.class) +public final class Prefix extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getPrefix method can return null.", + method = "getPrefix", + args = {} + ) + public void testGetPrefix1() throws Throwable { + Document doc; + Node createdNode; + String prefix; + doc = (Document) load("staffNS", builder); + createdNode = doc.createElement("test:employee"); + prefix = createdNode.getPrefix(); + assertNull("throw_Null", prefix); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies positive functionality of getPrefix method.", + method = "getPrefix", + args = {} + ) + public void testGetPrefix2() throws Throwable { + Document doc; + NodeList elementList; + Node testEmployee; + Node textNode; + String prefix; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:employeeId"); + testEmployee = elementList.item(0); + assertNotNull("empEmployeeNotNull", testEmployee); + textNode = testEmployee.getFirstChild(); + prefix = textNode.getPrefix(); + assertNull("textNodePrefix", prefix); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies positive functionality of getPrefix method.", + method = "getPrefix", + args = {} + ) + public void testGetPrefix3() throws Throwable { + Document doc; + NodeList elementList; + Node testEmployee; + String prefix; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:employee"); + testEmployee = elementList.item(0); + assertNotNull("empEmployeeNotNull", testEmployee); + prefix = testEmployee.getPrefix(); + assertEquals("prefix", "emp", prefix); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getPrefix method returns null.", + method = "getPrefix", + args = {} + ) + public void testGetPrefix4() throws Throwable { + Document doc; + NodeList elementList; + Node testEmployee; + String prefix; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + testEmployee = elementList.item(0); + prefix = testEmployee.getPrefix(); + assertNull("throw_Null", prefix); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.", + method = "getPrefix", + args = {} + ) + public void testGetPrefix5() throws Throwable { + Document doc; + NodeList elementList; + Element addrNode; + Attr addrAttr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + addrNode = (Element) elementList.item(0); + assertNotNull("empAddrNotNull", addrNode); + addrAttr = addrNode.getAttributeNode("emp:domestic"); + + { + boolean success = false; + try { + addrAttr.setPrefix("xmlns"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getPrefix method throws DOMException with INVALID_CHARACTER_ERR code.", + method = "getPrefix", + args = {} + ) + public void _testGetPrefix6() throws Throwable { + Document doc; + NodeList elementList; + Node employeeNode; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + employeeNode = elementList.item(0); + + { + boolean success = false; + try { + employeeNode.setPrefix("pre^fix xmlns='http//www.nist.gov'"); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("throw_INVALID_CHARACTER_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.", + method = "getPrefix", + args = {} + ) + public void testGetPrefix7() throws Throwable { + Document doc; + NodeList elementList; + Node employeeNode; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + employeeNode = elementList.item(0); + + { + boolean success = false; + try { + employeeNode.setPrefix("emp::"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + +// Assumes validation. +// public void testGetPrefix8() throws Throwable { +// Document doc; +// NodeList genderList; +// Node genderNode; +// Node entRef; +// Node entElement; +// +// int nodeType; +// doc = (Document) load("staff", builder); +// genderList = doc.getElementsByTagName("gender"); +// genderNode = genderList.item(2); +// entRef = genderNode.getFirstChild(); +// nodeType = (int) entRef.getNodeType(); +// +// if (1 == nodeType) { +// entRef = doc.createEntityReference("ent4"); +// assertNotNull("createdEntRefNotNull", entRef); +// } +// entElement = entRef.getFirstChild(); +// assertNotNull("entElement", entElement); +// doc.createElement("text3"); +// +// { +// boolean success = false; +// try { +// entElement.setPrefix("newPrefix"); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success); +// } +// } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.", + method = "getPrefix", + args = {} + ) + public void _testGetPrefix9() throws Throwable { + Document doc; + NodeList elementList; + Element addrNode; + Attr addrAttr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + addrNode = (Element) elementList.item(3); + addrAttr = addrNode.getAttributeNode("xmlns"); + + { + boolean success = false; + try { + addrAttr.setPrefix("xxx"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.", + method = "getPrefix", + args = {} + ) + public void testGetPrefix10() throws Throwable { + Document doc; + NodeList elementList; + Node employeeNode; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + employeeNode = elementList.item(1); + + { + boolean success = false; + try { + employeeNode.setPrefix("xml"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.", + method = "getPrefix", + args = {} + ) + public void testGetPrefix11() throws Throwable { + Document doc; + NodeList elementList; + Node employeeNode; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + employeeNode = elementList.item(1); + employeeNode.getNamespaceURI(); + + { + boolean success = false; + try { + employeeNode.setPrefix("employee1"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/PublicId.java b/xml/src/test/java/tests/org/w3c/dom/PublicId.java new file mode 100644 index 0000000..8165b2c --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/PublicId.java @@ -0,0 +1,91 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.DocumentType; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getPublicId()" method of a documenttype node contains + * the public identifier associated with the external subset. + * + * Retrieve the documenttype. + * Apply the "getPublicId()" method. The string "STAFF" should be + * returned. +* @author NIST +* @author Mary Brady +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-publicId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-publicId</a> +*/ +@TestTargetClass(DocumentType.class) +public final class PublicId extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getPublicId", + args = {} + ) + public void testGetPublicId() throws Throwable { + Document doc; + DocumentType docType; + String publicId; + doc = (Document) load("staffNS", builder); + docType = doc.getDoctype(); + publicId = docType.getPublicId(); + assertEquals("throw_Equals", "STAFF", publicId); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/RemoveAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/RemoveAttributeNS.java new file mode 100644 index 0000000..6a84d1b --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/RemoveAttributeNS.java @@ -0,0 +1,147 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargetClass; + +import javax.xml.parsers.DocumentBuilder; + +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * The "removeAttributeNS(namespaceURI,localName)" method for an attribute + * causes the DOMException NO_MODIFICATION_ALLOWED_ERR to be raised if the node + * is readonly. + * + * Obtain the children of the THIRD "gender" element. The elements content is an + * entity reference. Try to remove an attribute from the entity reference by + * executing the "removeAttributeNS(namespaceURI,localName)" method. This causes + * a NO_MODIFICATION_ALLOWED_ERR DOMException to be thrown. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NO_MODIFICATION_ALLOWED_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NO_MODIFICATION_ALLOWED_ERR'])</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElRemAtNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElRemAtNS</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElRemAtNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NO_MODIFICATION_ALLOWED_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElRemAtNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NO_MODIFICATION_ALLOWED_ERR'])</a> + */ +@TestTargetClass(Attr.class) +public final class RemoveAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ +// Assumes validation. +// public void testRemoveAttributeNS1() throws Throwable { +// Document doc; +// NodeList genderList; +// Node gender; +// Node gen; +// NodeList gList; +// Element genElement; +// int nodeType; +// doc = (Document) load("staffNS", builder); +// genderList = doc.getElementsByTagName("gender"); +// gender = genderList.item(2); +// gen = gender.getFirstChild(); +// nodeType = (int) gen.getNodeType(); +// +// if (1 == nodeType) { +// gen = doc.createEntityReference("ent4"); +// assertNotNull("createdEntRefNotNull", gen); +// } +// gList = gen.getChildNodes(); +// genElement = (Element) gList.item(0); +// assertNotNull("notnull", genElement); +// +// { +// boolean success = false; +// try { +// genElement.removeAttributeNS("www.xyz.com", "local1"); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success); +// } +// } + +// Assumes validation +// public void testRemoveAttributeNS2() throws Throwable { +// Document doc; +// NodeList elementList; +// Node testAddr; +// Attr addrAttr; +// String attr; +// String namespaceURI; +// String localName; +// String prefix; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("emp:address"); +// testAddr = elementList.item(0); +// ((Element) /* Node */testAddr).removeAttributeNS("http://www.nist.gov", +// "local1"); +// elementList = doc.getElementsByTagName("emp:address"); +// testAddr = elementList.item(0); +// addrAttr = ((Element) /* Node */testAddr).getAttributeNodeNS( +// "http://www.nist.gov", "local1"); +// attr = ((Element) /* Node */testAddr).getAttributeNS( +// "http://www.nist.gov", "local1"); +// namespaceURI = addrAttr.getNamespaceURI(); +// localName = addrAttr.getLocalName(); +// prefix = testAddr.getPrefix(); +// assertEquals("attr", "FALSE", attr); +// assertEquals("uri", "http://www.nist.gov", namespaceURI); +// assertEquals("lname", "local1", localName); +// assertEquals("prefix", "emp", prefix); +// } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/RemoveNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/RemoveNamedItemNS.java new file mode 100644 index 0000000..e745e74 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/RemoveNamedItemNS.java @@ -0,0 +1,178 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "removeNamedItemNS(namespaceURI,localName)" method for a NamedNodeMap + * should remove a node specified by localName and namespaceURI. + * + * Retrieve a list of elements with tag name "address". Access the second + * element from the list and get its attributes. Try to remove the attribute + * node with local name "domestic" and namespace uri "http://www.usa.com" with + * method removeNamedItemNS(namespaceURI,localName). Check to see if the node + * has been removed. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1074577549">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1074577549</a> + */ +@TestTargetClass(NamedNodeMap.class) +public final class RemoveNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify DOMException exception.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS1() throws Throwable { + Document doc; + NodeList elementList; + Node testAddress; + NamedNodeMap attributes; + Attr newAttr; + Node removedNode; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + testAddress = elementList.item(1); + attributes = testAddress.getAttributes(); + removedNode = attributes.removeNamedItemNS("http://www.usa.com", + "domestic"); + assertNotNull("retval", removedNode); + newAttr = (Attr) attributes.getNamedItem("dmstc:domestic"); + assertNull("nodeRemoved", newAttr); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Verifies DOMException with NOT_FOUND_ERR code.", + method = "removeNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testRemoveNamedItemNS2() throws Throwable { + String namespaceURI = "http://www.usa.com"; + String localName = "domest"; + Document doc; + NodeList elementList; + Node testAddress; + NamedNodeMap attributes; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + testAddress = elementList.item(1); + attributes = testAddress.getAttributes(); + + { + boolean success = false; + try { + attributes.removeNamedItemNS(namespaceURI, + localName); + } catch (DOMException ex) { + success = (ex.code == DOMException.NOT_FOUND_ERR); + } + assertTrue("throw_NOT_FOUND_ERR", success); + } + } + +// Assumes validation. +// public void testRemoveNamedItemNS3() throws Throwable { +// String namespaceURI = "http://www.w3.org/2000/xmlns/"; +// String localName = "local1"; +// Document doc; +// NodeList elementList; +// Node testAddress; +// NodeList nList; +// Node child; +// NodeList n2List; +// Node child2; +// NamedNodeMap attributes; +// +// int nodeType; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("gender"); +// testAddress = elementList.item(2); +// nList = testAddress.getChildNodes(); +// child = nList.item(0); +// nodeType = (int) child.getNodeType(); +// +// if (1 == nodeType) { +// child = doc.createEntityReference("ent4"); +// assertNotNull("createdEntRefNotNull", child); +// } +// n2List = child.getChildNodes(); +// child2 = n2List.item(0); +// assertNotNull("notnull", child2); +// attributes = child2.getAttributes(); +// +// { +// boolean success = false; +// try { +// attributes.removeNamedItemNS(namespaceURI, +// localName); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success); +// } +// } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/SetAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/SetAttributeNS.java new file mode 100644 index 0000000..58c146f --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/SetAttributeNS.java @@ -0,0 +1,353 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.DOMException; +import org.w3c.dom.Attr; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "setAttributeNS(namespaceURI,qualifiedName,Value)" method raises a + * INVALID_CHARACTER_ERR DOMException if the specified prefix contains an + * illegal character. + * + * Attempt to add a new attribute on the first employee node. An exception + * should be raised since the "qualifiedName" has an invalid character. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INVALID_CHARACTER_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INVALID_CHARACTER_ERR'])</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAttrNS</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAttrNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INVALID_CHARACTER_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAttrNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INVALID_CHARACTER_ERR'])</a> + */ +@TestTargetClass(Element.class) +public final class SetAttributeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with INVALID_CHARACTER_ERR code.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS1() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String qualifiedName = "emp:qual?name"; + Document doc; + NodeList elementList; + Node testAddr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + testAddr = elementList.item(0); + + { + boolean success = false; + try { + ((Element) /* Node */testAddr).setAttributeNS(namespaceURI, + qualifiedName, "newValue"); + } catch (DOMException ex) { + success = (ex.code == DOMException.INVALID_CHARACTER_ERR); + } + assertTrue("throw_INVALID_CHARACTER_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS2() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String qualifiedName = "emp:"; + Document doc; + NodeList elementList; + Node testAddr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:employee"); + testAddr = elementList.item(0); + + { + boolean success = false; + try { + ((Element) /* Node */testAddr).setAttributeNS(namespaceURI, + qualifiedName, "newValue"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + +// Assumes validation. +// public void testSetAttributeNS3() throws Throwable { +// String namespaceURI = "www.xyz.com"; +// String qualifiedName = "emp:local1"; +// Document doc; +// NodeList genderList; +// Node gender; +// NodeList genList; +// Node gen; +// NodeList gList; +// Element genElement; +// int nodeType; +// doc = (Document) load("staffNS", builder); +// genderList = doc.getElementsByTagName("gender"); +// gender = genderList.item(2); +// genList = gender.getChildNodes(); +// gen = genList.item(0); +// nodeType = (int) gen.getNodeType(); +// +// if (1 == nodeType) { +// gen = doc.createEntityReference("ent4"); +// assertNotNull("createdEntRefNotNull", gen); +// } +// gList = gen.getChildNodes(); +// genElement = (Element) gList.item(0); +// assertNotNull("notnull", genElement); +// +// { +// boolean success = false; +// try { +// genElement.setAttributeNS(namespaceURI, qualifiedName, +// "newValue"); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success); +// } +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "setAttributeNS", + args = {String.class, String.class, String.class} + ) + public void testSetAttributeNS4() throws Throwable { + Document doc; + NodeList elementList; + Node testAddr; + Attr addrAttr; + String resultAttr; + String resultNamespaceURI; + String resultLocalName; + String resultPrefix; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + ((Element) /* Node */testAddr).setAttributeNS("http://www.nist.gov", + "newprefix:zone", "newValue"); + addrAttr = ((Element) /* Node */testAddr).getAttributeNodeNS( + "http://www.nist.gov", "zone"); + resultAttr = ((Element) /* Node */testAddr).getAttributeNS( + "http://www.nist.gov", "zone"); + assertEquals("attrValue", "newValue", resultAttr); + resultNamespaceURI = addrAttr.getNamespaceURI(); + assertEquals("nsuri", "http://www.nist.gov", resultNamespaceURI); + resultLocalName = addrAttr.getLocalName(); + assertEquals("lname", "zone", resultLocalName); + resultPrefix = addrAttr.getPrefix(); + assertEquals("prefix", "newprefix", resultPrefix); + } + + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS5() throws Throwable { + String localName = "newAttr"; + String namespaceURI = "http://www.newattr.com"; + String qualifiedName = "emp:newAttr"; + Document doc; + NodeList elementList; + Node testAddr; + + String resultAttr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + ((Element) /* Node */testAddr).setAttributeNS(namespaceURI, + qualifiedName, "<newValue>"); + resultAttr = ((Element) /* Node */testAddr).getAttributeNS( + namespaceURI, localName); + assertEquals("throw_Equals", "<newValue>", resultAttr); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS6() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String qualifiedName = "xml:qualifiedName"; + Document doc; + NodeList elementList; + Node testAddr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + testAddr = elementList.item(0); + + { + boolean success = false; + try { + ((Element) /* Node */testAddr).setAttributeNS(namespaceURI, + qualifiedName, "newValue"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS7() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String qualifiedName = "xmlns"; + Document doc; + NodeList elementList; + Node testAddr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("employee"); + testAddr = elementList.item(0); + + { + boolean success = false; + try { + ((Element) /* Node */testAddr).setAttributeNS(namespaceURI, + qualifiedName, "newValue"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive functionality.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS9() throws Throwable { + String localName = "newAttr"; + String namespaceURI = "http://www.newattr.com"; + String qualifiedName = "emp:newAttr"; + Document doc; + NodeList elementList; + Node testAddr; + Attr addrAttr; + String resultAttr; + String resultNamespaceURI; + String resultLocalName; + String resultPrefix; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + ((Element) /* Node */testAddr).setAttributeNS(namespaceURI, + qualifiedName, "newValue"); + addrAttr = ((Element) /* Node */testAddr).getAttributeNodeNS( + namespaceURI, localName); + resultAttr = ((Element) /* Node */testAddr).getAttributeNS( + namespaceURI, localName); + assertEquals("attrValue", "newValue", resultAttr); + resultNamespaceURI = addrAttr.getNamespaceURI(); + assertEquals("nsuri", "http://www.newattr.com", resultNamespaceURI); + resultLocalName = addrAttr.getLocalName(); + assertEquals("lname", "newAttr", resultLocalName); + resultPrefix = addrAttr.getPrefix(); + assertEquals("prefix", "emp", resultPrefix); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with NAMESPACE_ERR code.", + method = "setAttributeNS", + args = {java.lang.String.class, java.lang.String.class, java.lang.String.class} + ) + public void testSetAttributeNS10() throws Throwable { + String namespaceURI = "http://www.example.gov"; + Document doc; + NodeList elementList; + Node testAddr; + doc = (Document) load("hc_staff", builder); + elementList = doc.getElementsByTagName("em"); + testAddr = elementList.item(0); + + { + boolean success = false; + try { + ((Element) /* Node */testAddr).setAttributeNS(namespaceURI, "", + "newValue"); + } catch (DOMException ex) { + success = (ex.code == DOMException.NAMESPACE_ERR); + } + assertTrue("throw_NAMESPACE_ERR", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/SetAttributeNodeNS.java b/xml/src/test/java/tests/org/w3c/dom/SetAttributeNodeNS.java new file mode 100644 index 0000000..3960a4f --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/SetAttributeNodeNS.java @@ -0,0 +1,237 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001-2004 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "setAttributeNode(newAttr)" method raises an "INUSE_ATTRIBUTE_ERR + * DOMException if the "newAttr" is already an attribute of another element. + * + * Retrieve the first emp:address and append a newly created element. The + * "createAttributeNS(namespaceURI,qualifiedName)" and + * "setAttributeNodeNS(newAttr)" methods are invoked to create and add a new + * attribute to the newly created Element. The "setAttributeNodeNS(newAttr)" + * method is once again called to add the new attribute causing an exception to + * be raised since the attribute is already an attribute of another element. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS</a> + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAtNodeNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAtNodeNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])</a> + */ +@TestTargetClass(Element.class) +public final class SetAttributeNodeNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with INUSE_ATTRIBUTE_ERR code.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNode1() throws Throwable { + String namespaceURI = "http://www.newattr.com"; + String qualifiedName = "emp:newAttr"; + Document doc; + Element newElement; + Attr newAttr; + NodeList elementList; + Node testAddr; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + newElement = doc.createElement("newElement"); + testAddr.appendChild(newElement); + newAttr = doc.createAttributeNS(namespaceURI, qualifiedName); + newElement.setAttributeNodeNS(newAttr); + + { + boolean success = false; + try { + ((Element) /* Node */testAddr).setAttributeNodeNS(newAttr); + } catch (DOMException ex) { + success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR); + } + assertTrue("throw_INUSE_ATTRIBUTE_ERR", success); + } + } + +// Assumes validation. +// public void testSetAttributeNode2() throws Throwable { +// Document doc; +// NodeList genderList; +// Node gender; +// NodeList genList; +// Node gen; +// NodeList gList; +// Element genElement; +// Attr newAttr; +// +// doc = (Document) load("staffNS", builder); +// +// if (!factory.isExpandEntityReferences()) { +// genderList = doc.getElementsByTagName("gender"); +// gender = genderList.item(2); +// genList = gender.getChildNodes(); +// gen = genList.item(0); +// } else { +// gen = doc.createEntityReference("ent4"); +// } +// +// gList = gen.getChildNodes(); +// genElement = (Element) gList.item(0); +// assertNotNull("notnull", genElement); +// newAttr = doc.createAttributeNS("www.xyz.com", "emp:local1"); +// +// { +// boolean success = false; +// try { +// genElement.setAttributeNodeNS(newAttr); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success); +// } +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNode3() throws Throwable { + String namespaceURI = "http://www.newattr.com"; + String qualifiedName = "emp:newAttr"; + Document doc; + NodeList elementList; + Node testAddr; + Attr newAttr; + Attr newAddrAttr; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + newAttr = doc.createAttributeNS(namespaceURI, qualifiedName); + newAddrAttr = ((Element) /* Node */testAddr) + .setAttributeNodeNS(newAttr); + assertNull("throw_Null", newAddrAttr); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Doesn't verify DOMException.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNode4() throws Throwable { + Document doc; + NodeList elementList; + Node testAddr; + Attr newAttr; + Attr newAddrAttr; + String newName; + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("emp:address"); + testAddr = elementList.item(0); + assertNotNull("empAddrNotNull", testAddr); + newAttr = doc.createAttributeNS("http://www.nist.gov", "xxx:domestic"); + newAddrAttr = ((Element) /* Node */testAddr) + .setAttributeNodeNS(newAttr); + newName = newAddrAttr.getNodeName(); + assertEquals("nodeName", "emp:domestic", newName); + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with WRONG_DOCUMENT_ERR code.", + method = "setAttributeNodeNS", + args = {org.w3c.dom.Attr.class} + ) + public void testSetAttributeNode5() throws Throwable { + String namespaceURI = "http://www.newattr.com"; + String qualifiedName = "emp:newAttr"; + Document doc1; + Document doc2; + Attr newAttr; + NodeList elementList; + Node testAddr; + + doc1 = (Document) load("staffNS", builder); + doc2 = (Document) load("staffNS", builder); + newAttr = doc2.createAttributeNS(namespaceURI, qualifiedName); + elementList = doc1.getElementsByTagName("emp:address"); + testAddr = elementList.item(0); + + { + boolean success = false; + try { + ((Element) /* Node */testAddr).setAttributeNodeNS(newAttr); + } catch (DOMException ex) { + success = (ex.code == DOMException.WRONG_DOCUMENT_ERR); + } + assertTrue("throw_WRONG_DOCUMENT_ERR", success); + } + } +} diff --git a/xml/src/test/java/tests/org/w3c/dom/SetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/SetNamedItemNS.java new file mode 100644 index 0000000..ae364ec --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/SetNamedItemNS.java @@ -0,0 +1,248 @@ + +/* +This Java source file was generated by test-to-java.xsl +and is a derived work from the source document. +The source document contained the following notice: + + + +Copyright (c) 2001 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + +*/ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.DOMException; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "setNamedItemNS(arg)" method for a + * NamedNodeMap should raise INUSE_ATTRIBUTE_ERR DOMException if + * arg is an Attr that is already an attribute of another Element object. + * + * Retrieve an attr node from the third "address" element whose local name + * is "domestic" and namespaceURI is "http://www.netzero.com". + * Invoke method setNamedItemNS(arg) on the map of the first "address" element with + * arg being the attr node from above. Method should raise + * INUSE_ATTRIBUTE_ERR DOMException. +* @author NIST +* @author Mary Brady +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])</a> +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS</a> +* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-setNamedItemNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-setNamedItemNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])</a> +*/ +@TestTargetClass(NamedNodeMap.class) +public final class SetNamedItemNS extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration2()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * @throws Throwable Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with INUSE_ATTRIBUTE_ERR code.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS1() throws Throwable { + Document doc; + NodeList elementList; + Node anotherElement; + NamedNodeMap anotherMap; + Node arg; + Node testAddress; + NamedNodeMap map; + + doc = (Document) load("staffNS", builder); + elementList = doc.getElementsByTagName("address"); + anotherElement = elementList.item(2); + anotherMap = anotherElement.getAttributes(); + arg = anotherMap.getNamedItemNS("http://www.netzero.com", "domestic"); + testAddress = elementList.item(0); + map = testAddress.getAttributes(); + + { + boolean success = false; + try { + map.setNamedItemNS(arg); + } catch (DOMException ex) { + success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR); + } + assertTrue("throw_INUSE_ATTRIBUTE_ERR", success); + } +} + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies DOMException with WRONG_DOCUMENT_ERR code.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS2() throws Throwable { + String namespaceURI = "http://www.usa.com"; + String qualifiedName = "dmstc:domestic"; + Document doc; + Document anotherDoc; + Node arg; + NodeList elementList; + Node testAddress; + NamedNodeMap attributes; + + doc = (Document) load("staffNS", builder); + anotherDoc = (Document) load("staffNS", builder); + arg = anotherDoc.createAttributeNS(namespaceURI, qualifiedName); + arg.setNodeValue("Maybe"); + elementList = doc.getElementsByTagName("address"); + testAddress = elementList.item(0); + attributes = testAddress.getAttributes(); + + { + boolean success = false; + try { + attributes.setNamedItemNS(arg); + } catch (DOMException ex) { + success = (ex.code == DOMException.WRONG_DOCUMENT_ERR); + } + assertTrue("throw_WRONG_DOCUMENT_ERR", success); + } + } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive fnctionality.", + method = "getNamedItemNS", + args = {java.lang.String.class, java.lang.String.class} + ) + public void testSetNamedItemNS3() throws Throwable { + String namespaceURI = "http://www.nist.gov"; + String qualifiedName = "prefix:newAttr"; + Document doc; + Node arg; + NodeList elementList; + Node testAddress; + NamedNodeMap attributes; + Node retnode; + String value; + + doc = (Document) load("staffNS", builder); + arg = doc.createAttributeNS(namespaceURI, qualifiedName); + arg.setNodeValue("newValue"); + elementList = doc.getElementsByTagName("address"); + testAddress = elementList.item(0); + attributes = testAddress.getAttributes(); + attributes.setNamedItemNS(arg); + retnode = attributes.getNamedItemNS(namespaceURI, "newAttr"); + value = retnode.getNodeValue(); + assertEquals("throw_Equals", "newValue", value); + } + +// Assumes validation. +// public void testSetNamedItemNS4() throws Throwable { +// String namespaceURI = "http://www.w3.org/2000/xmlns/"; +// String localName = "local1"; +// Document doc; +// NodeList elementList; +// Node testAddress; +// NodeList nList; +// Node child; +// NodeList n2List; +// Node child2; +// NamedNodeMap attributes; +// Node arg; +// +// int nodeType; +// doc = (Document) load("staffNS", builder); +// elementList = doc.getElementsByTagName("gender"); +// testAddress = elementList.item(2); +// nList = testAddress.getChildNodes(); +// child = nList.item(0); +// nodeType = (int) child.getNodeType(); +// +// if (1 == nodeType) { +// child = doc.createEntityReference("ent4"); +// assertNotNull("createdEntRefNotNull", child); +// } +// n2List = child.getChildNodes(); +// child2 = n2List.item(0); +// assertNotNull("notnull", child2); +// attributes = child2.getAttributes(); +// arg = attributes.getNamedItemNS(namespaceURI, localName); +// +// { +// boolean success = false; +// try { +// attributes.setNamedItemNS(arg); +// } catch (DOMException ex) { +// success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR); +// } +// assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success); +// } +// } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies positive fnctionality.", + method = "setNamedItemNS", + args = {org.w3c.dom.Node.class} + ) + public void testSetNamedItemNS5() throws Throwable { + String namespaceURI = "http://www.usa.com"; + String qualifiedName = "dmstc:domestic"; + Document doc; + Node arg; + NodeList elementList; + Node testAddress; + NamedNodeMap attributes; + Node retnode; + String value; + doc = (Document) load("staffNS", builder); + arg = doc.createAttributeNS(namespaceURI, qualifiedName); + arg.setNodeValue("newValue"); + elementList = doc.getElementsByTagName("address"); + testAddress = elementList.item(0); + attributes = testAddress.getAttributes(); + retnode = attributes.setNamedItemNS(arg); + value = retnode.getNodeValue(); + assertEquals("throw_Equals", "Yes", value); + } + +} + diff --git a/xml/src/test/java/tests/org/w3c/dom/SystemId.java b/xml/src/test/java/tests/org/w3c/dom/SystemId.java new file mode 100644 index 0000000..3e1b903 --- /dev/null +++ b/xml/src/test/java/tests/org/w3c/dom/SystemId.java @@ -0,0 +1,94 @@ +/* + This Java source file was generated by test-to-java.xsl + and is a derived work from the source document. + The source document contained the following notice: + + + + Copyright (c) 2001 World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). All + Rights Reserved. This program is distributed under the W3C's Software + Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + + + */ + +package tests.org.w3c.dom; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import org.w3c.dom.DocumentType; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; + +/** + * The "getSystemId()" method of a documenttype node contains the system + * identifier associated with the external subset. + * + * Retrieve the documenttype. Apply the "getSystemId()" method. The string + * "staffNS.dtd" should be returned. + * + * @author NIST + * @author Mary Brady + * @see <a + * href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-systemId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-systemId</a> + */ +@TestTargetClass(DocumentType.class) +public final class SystemId extends DOMTestCase { + + DOMDocumentBuilderFactory factory; + + DocumentBuilder builder; + + protected void setUp() throws Exception { + super.setUp(); + try { + factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory + .getConfiguration1()); + builder = factory.getBuilder(); + } catch (Exception e) { + fail("Unexpected exception" + e.getMessage()); + } + } + + protected void tearDown() throws Exception { + factory = null; + builder = null; + super.tearDown(); + } + + /** + * Runs the test case. + * + * @throws Throwable + * Any uncaught exception causes test to fail + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "", + method = "getSystemId", + args = {} + ) + public void testGetSystemId() throws Throwable { + Document doc; + DocumentType docType; + String systemId; + + doc = (Document) load("staffNS", builder); + docType = doc.getDoctype(); + systemId = docType.getSystemId(); + assertURIEquals("systemId", null, null, null, "staffNS.dtd", null, + null, null, null, systemId); + } + +} diff --git a/xml/src/test/java/tests/xml/AllTests.java b/xml/src/test/java/tests/xml/AllTests.java new file mode 100644 index 0000000..eefae50 --- /dev/null +++ b/xml/src/test/java/tests/xml/AllTests.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.xml; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AllTests { + + public static Test suite() { + TestSuite suite = tests.TestSuiteFactory.createTestSuite(); + + suite.addTestSuite(SimpleParserTest.class); + suite.addTestSuite(SimpleBuilderTest.class); + + //suite.addTest(tests.org.w3c.dom.AllTests.suite()); + suite.addTest(tests.api.javax.xml.parsers.AllTests.suite()); + + suite.addTest(tests.api.org.xml.sax.AllTests.suite()); + + return suite; + } + +} diff --git a/xml/src/test/java/tests/xml/SimpleBuilderTest.java b/xml/src/test/java/tests/xml/SimpleBuilderTest.java new file mode 100644 index 0000000..1a555c6 --- /dev/null +++ b/xml/src/test/java/tests/xml/SimpleBuilderTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.xml; + +import dalvik.annotation.BrokenTest; +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import junit.framework.TestCase; + +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +@TestTargetClass(DocumentBuilder.class) +public class SimpleBuilderTest extends TestCase { + + private DocumentBuilder builder; + + protected void setUp() throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setValidating(false); + factory.setNamespaceAware(true); + + builder = factory.newDocumentBuilder(); + } + + protected void tearDown() throws Exception { + builder = null; + } + + private String getTextContent(Node node) { + String result = (node instanceof Text ? ((Text) node).getData() : ""); + + Node child = node.getFirstChild(); + while (child != null) { + result = result + getTextContent(child); + child = child.getNextSibling(); + } + + return result; + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Regression test.", + method = "parse", + args = {java.io.InputStream.class} + ) + public void testGoodFile1() throws Exception { + Document document = builder.parse(getClass().getResourceAsStream( + "/SimpleBuilderTest.xml")); + + Element root = document.getDocumentElement(); + assertNotNull(root); + assertEquals("http://www.foo.bar", root.getNamespaceURI()); + assertEquals("t", root.getPrefix()); + assertEquals("stuff", root.getLocalName()); + + NodeList list = root.getElementsByTagName("nestedStuff"); + assertNotNull(list); + assertEquals(list.getLength(), 4); + + Element one = (Element) list.item(0); + Element two = (Element) list.item(1); + Element three = (Element) list.item(2); + Element four = (Element) list.item(3); + + assertEquals("This space intentionally left blank.", + getTextContent(one)); + assertEquals("Nothing to see here - please get along!", + getTextContent(two)); + assertEquals("Rent this space!", getTextContent(three)); + assertEquals("", getTextContent(four)); + + assertEquals("eins", one.getAttribute("one")); + assertEquals("zwei", two.getAttribute("two")); + assertEquals("drei", three.getAttribute("three")); + + assertEquals("vier", four.getAttribute("t:four")); + assertEquals("vier", four.getAttributeNS("http://www.foo.bar", "four")); + + list = document.getChildNodes(); + assertNotNull(list); + + String proinst = ""; + String comment = ""; + + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + + if (node instanceof ProcessingInstruction) { + proinst = proinst + node.getNodeValue(); + } else if (node instanceof Comment) { + comment = comment + node.getNodeValue(); + } + } + + assertEquals("The quick brown fox jumps over the lazy dog.", proinst); + assertEquals(" Fragile! Handle me with care! ", comment); + } + @TestTargetNew( + level = TestLevel.ADDITIONAL, + method = "!todo parse", + args = {java.io.InputStream.class} + ) + @BrokenTest("Doesn't verify anything.") + public void testGoodFile2() throws Exception { + Document document = builder.parse(getClass().getResourceAsStream( + "/staffNS.xml")); + + Element root = document.getDocumentElement(); + assertNotNull(root); + + // dump("", root); + } + + private void dump(String prefix, Element element) { + System.out.print(prefix + "<" + element.getTagName()); + + NamedNodeMap attrs = element.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + Node item = attrs.item(i); + System.out.print(" " + item.getNodeName() + "=" + item.getNodeValue()); + } + + System.out.println(">"); + + NodeList children = element.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node item = children.item(i); + if (item instanceof Element) { + dump(prefix + " ", (Element)item); + } + } + + System.out.println(prefix + "</" + element.getTagName() + ">"); + } +} diff --git a/xml/src/test/java/tests/xml/SimpleParserTest.java b/xml/src/test/java/tests/xml/SimpleParserTest.java new file mode 100644 index 0000000..4651039 --- /dev/null +++ b/xml/src/test/java/tests/xml/SimpleParserTest.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.xml; + +import dalvik.annotation.TestTargets; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargetClass; + +import junit.framework.TestCase; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +@TestTargetClass(SAXParser.class) +public class SimpleParserTest extends TestCase implements ContentHandler { + + private SAXParser parser; + + private StringBuffer instructions; + + private Map<String, String> namespaces1; + private Map<String, String> namespaces2; + + private StringBuffer elements1; + private StringBuffer elements2; + + private Map<String, String> attributes1; + private Map<String, String> attributes2; + + private StringBuffer text; + + @Override + protected void setUp() throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + factory.setNamespaceAware(true); + + parser = factory.newSAXParser(); + parser.getXMLReader().setContentHandler(this); + + instructions = new StringBuffer(); + namespaces1 = new HashMap<String, String>(); + namespaces2 = new HashMap<String, String>(); + elements1 = new StringBuffer(); + elements2 = new StringBuffer(); + attributes1 = new HashMap<String, String>(); + attributes2 = new HashMap<String, String>(); + text = new StringBuffer(); + } + + @Override + protected void tearDown() throws Exception { + instructions = null; + parser = null; + namespaces1 = null; + namespaces2 = null; + attributes1 = null; + attributes2 = null; + elements1 = null; + elements2 = null; + text = null; + } + + public void characters(char[] ch, int start, int length) { + + String s = new String(ch, start, length).trim(); + if (s.length() != 0) { + if (text.length() != 0) { + text.append(","); + } + + text.append(s); + } + } + + public void endDocument() { + } + + public void endElement(String uri, String localName, String qName) { + } + + public void endPrefixMapping(String prefix) { + } + + public void ignorableWhitespace(char[] ch, int start, int length) { + } + + public void processingInstruction(String target, String data) { + String s = target + ":" + data; + + if (instructions.length() != 0) { + instructions.append(","); + } + + instructions.append(s); + } + + public void setDocumentLocator(Locator locator) { + } + + public void skippedEntity(String name) { + } + + public void startDocument() { + } + + public void startElement(String uri, String localName, String qName, + Attributes atts) { + + if (elements1.length() != 0) { + elements1.append(","); + } + + elements1.append(localName); + + if (!"".equals(uri)) { + namespaces1.put(localName, uri); + } + + for (int i = 0; i < atts.getLength(); i++) { + attributes1.put(atts.getLocalName(i), atts.getValue(i)); + } + + if (elements2.length() != 0) { + elements2.append(","); + } + + elements2.append(qName); + + if (!"".equals(uri)) { + namespaces2.put(qName, uri); + } + + for (int i = 0; i < atts.getLength(); i++) { + attributes2.put(atts.getQName(i), atts.getValue(i)); + } + } + + public void startPrefixMapping(String prefix, String uri) { + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "", + method = "parse", + args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class} + ) + public void testWorkingFile1() throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + factory.setNamespaceAware(true); + + SAXParser parser = factory.newSAXParser(); + parser.getXMLReader().setContentHandler(this); + + parser.parse(getClass().getResourceAsStream("/SimpleParserTest.xml"), + (DefaultHandler) null); + + assertEquals("The:quick,brown:fox", instructions.toString()); + + assertEquals("stuff,nestedStuff,nestedStuff,nestedStuff", elements1 + .toString()); + + assertEquals("Some text here,some more here...", text.toString()); + + assertEquals("eins", attributes1.get("one")); + assertEquals("zwei", attributes1.get("two")); + assertEquals("drei", attributes1.get("three")); + + assertEquals("http://www.foobar.org", namespaces1.get("stuff")); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "", + method = "parse", + args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class} + ) + public void testWorkingFile2() throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setNamespaceAware(false); + factory.setFeature("http://xml.org/sax/features/namespace-prefixes", + true); + + SAXParser parser = factory.newSAXParser(); + parser.getXMLReader().setContentHandler(this); + parser.parse(getClass().getResourceAsStream("/SimpleParserTest.xml"), + (DefaultHandler) null); + + assertFalse(parser.isNamespaceAware()); + + assertEquals("The:quick,brown:fox", instructions.toString()); + + assertEquals("t:stuff,nestedStuff,nestedStuff,nestedStuff", elements2 + .toString()); + + assertEquals("Some text here,some more here...", text.toString()); + + assertEquals("eins", attributes2.get("one")); + assertEquals("zwei", attributes2.get("two")); + assertEquals("drei", attributes2.get("three")); + + assertEquals(0, namespaces2.size()); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify exceptions.", + method = "parse", + args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class} + ) + public void testEntityResolver() throws Exception { + final StringBuilder text = new StringBuilder(); + DefaultHandler handler = new DefaultHandler() { + public void characters(char[] ch, int start, int length) { + String s = new String(ch, start, length).trim(); + if (s.length() != 0) { + if (text.length() != 0) { + text.append(","); + } + text.append(s); + } + } + + public InputSource resolveEntity(String publicId, String systemId) + throws IOException, SAXException { + return new InputSource(new InputStreamReader( + new ByteArrayInputStream("test".getBytes()))); + } + }; + + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setValidating(false); + parser = spf.newSAXParser(); + parser.parse(this.getClass().getResourceAsStream("/staffEntRes.xml"), + handler); + assertTrue( + "resolved external entity must be in parser character stream", + text.toString().contains("test")); + } + @TestTargetNew( + level = TestLevel.PARTIAL, + notes = "Doesn't verify exceptions.", + method = "parse", + args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class} + ) + public void testGetValue() throws Exception{ + parser.parse(getClass().getResourceAsStream("/staffNS.xml"), + new DefaultHandler() { + boolean firstAddressElem = true; + @Override + public void startElement (String uri, String localName, + String qName, Attributes attributes) { + if(firstAddressElem && localName.equals("address")) { + firstAddressElem = false; + assertNotNull(attributes.getValue("http://www.usa.com", + "domestic")); + } + } + }); + } +} diff --git a/xml/src/test/resources/SimpleBuilderTest.xml b/xml/src/test/resources/SimpleBuilderTest.xml new file mode 100644 index 0000000..23edce7 --- /dev/null +++ b/xml/src/test/resources/SimpleBuilderTest.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> + +<!-- Fragile! --> + +<!-- Handle me with care! --> + +<?cmd The quick brown fox ?> + +<t:stuff xmlns:t="http://www.foo.bar" xmlns:u="http://www.bar.foo"> + + <nestedStuff one="eins">This space intentionally left blank.</nestedStuff> + + <nestedStuff two="zwei">Nothing to see here - please get along!</nestedStuff> + + <nestedStuff three="drei" title="">Rent this space!</nestedStuff> + + <nestedStuff t:four="vier"/> + +</t:stuff> + +<?cmd jumps over the lazy dog.?> diff --git a/xml/src/test/resources/SimpleParserTest.xml b/xml/src/test/resources/SimpleParserTest.xml new file mode 100644 index 0000000..e18bf3e --- /dev/null +++ b/xml/src/test/resources/SimpleParserTest.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?> + +<!-- This space intentionally left blank. --> + +<?The quick?> + +<t:stuff xmlns:t="http://www.foobar.org"> + + <nestedStuff one="eins"> Some text here </nestedStuff> + + <nestedStuff two="zwei"></nestedStuff> + + some more here... + + <nestedStuff three="drei" /> + +</t:stuff> + +<?brown fox?> diff --git a/xml/src/test/resources/hc_staff.xml b/xml/src/test/resources/hc_staff.xml new file mode 100644 index 0000000..2df9a74 --- /dev/null +++ b/xml/src/test/resources/hc_staff.xml @@ -0,0 +1,60 @@ +<?xml version="1.0"?><?TEST-STYLE PIDATA?> +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "xhtml1-strict.dtd" [ + <!ENTITY alpha "α"> + <!ENTITY beta "β"> + <!ENTITY gamma "γ"> + <!ENTITY delta "δ"> + <!ENTITY epsilon "ε"> + <!ENTITY alpha "ζ"> + <!NOTATION notation1 PUBLIC "notation1File"> + <!NOTATION notation2 SYSTEM "notation2File"> + <!ATTLIST acronym dir CDATA "ltr"> +]> +<!-- This is comment number 1.--> +<html xmlns='http://www.w3.org/1999/xhtml'><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>hc_staff</title><script type="text/javascript" src="svgunit.js"/><script charset="UTF-8" type="text/javascript" src="svgtest.js"/><script type='text/javascript'>function loadComplete() { startTest(); }</script></head><body onload="parent.loadComplete()"> + <p> + <em>EMP0001</em> + <strong>Margaret Martin</strong> + <code>Accountant</code> + <sup>56,000</sup> + <var>Female</var> + <acronym title="Yes">1230 North Ave. Dallas, Texas 98551</acronym> + </p> + <p> + <em>EMP0002</em> + <strong>Martha RaynoldsThis is a CDATASection with EntityReference number 2 &ent2; +This is an adjacent CDATASection with a reference to a tab &tab;</strong> + <code>Secretary</code> + <sup>35,000</sup> + <var>Female</var> + <acronym title="Yes" class="Yes">β Dallas, γ + 98554</acronym> + </p> + <p> + <em>EMP0003</em> + <strong>Roger + Jones</strong> + <code>Department Manager</code> + <sup>100,000</sup> + <var>δ</var> + <acronym title="Yes" class="No">PO Box 27 Irving, texas 98553</acronym> + </p> + <p> + <em>EMP0004</em> + <strong>Jeny Oconnor</strong> + <code>Personnel Director</code> + <sup>95,000</sup> + <var>Female</var> + <acronym title="Yes" class="Yα">27 South Road. Dallas, Texas 98556</acronym> + </p> + <p> + <em>EMP0005</em> + <strong>Robert Myers</strong> + <code>Computer Specialist</code> + <sup>90,000</sup> + <var>male</var> + <acronym title="Yes">1821 Nordic. Road, Irving Texas 98558</acronym> + </p> +</body></html> diff --git a/xml/src/test/resources/nwf/staff.dtd b/xml/src/test/resources/nwf/staff.dtd new file mode 100644 index 0000000..02a994d --- /dev/null +++ b/xml/src/test/resources/nwf/staff.dtd @@ -0,0 +1,17 @@ +<!ELEMENT employeeId (#PCDATA)> +<!ELEMENT name (#PCDATA)> +<!ELEMENT position (#PCDATA)> +<!ELEMENT salary (#PCDATA)> +<!ELEMENT address (#PCDATA)> +<!ELEMENT entElement ( #PCDATA ) > +<!ELEMENT gender ( #PCDATA | entElement )* > +<!ELEMENT employee (employeeId, name, position, salary, gender, address) > +<!ELEMENT staff (employee)+> +<!ATTLIST entElement + attr1 CDATA "Attr"> +<!ATTLIST address + domestic CDATA #IMPLIED + street CDATA "Yes"> +<!ATTLIST entElement + domestic CDATA "MALE" > + diff --git a/xml/src/test/resources/nwf/staff.xml b/xml/src/test/resources/nwf/staff.xml new file mode 100644 index 0000000..b600fcf --- /dev/null +++ b/xml/src/test/resources/nwf/staff.xml @@ -0,0 +1,57 @@ +<?xml version="1.0"?><?TEST-STYLE PIDATA?> +<!DOCTYPE staff SYSTEM "staff.dtd" [ + <!ENTITY ent1 "es"> + <!ENTITY ent2 "1900 Dallas Road"> + <!ENTITY ent3 "Texas"> + <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>"> + <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1> + <!ENTITY ent1 "This entity should be discarded"> + <!NOTATION notation1 PUBLIC "notation1File"> + <!NOTATION notation2 SYSTEM "notation2File"> +]> +<!-- This is comment number 1.--> +<staff> + <employee22> + <employeeId>EMP0001</employeeId> + <name>Margaret Martin</name> + <position>Accountant</position> + <salary>56,000</salary> + <gender>Female</gender> + <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address> + </employee> + <employee> + <employeeId>EMP0002</employeeId> + <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]> +<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name> + <position>Secretary</position> + <salary>35,000</salary> + <gender>Female</gender> + <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3; + 98554</address> + </employee> + <employee> + <employeeId>EMP0003</employeeId> + <name>Roger + Jones</name> + <position>Department Manager</position> + <salary>100,000</salary> + <gender>&ent4;</gender> + <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address> + </employee> + <employee> + <employeeId>EMP0004</employeeId> + <name>Jeny Oconnor</name> + <position>Personnel Director</position> + <salary>95,000</salary> + <gender>Female</gender> + <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address> + </employee> + <employee> + <employeeId>EMP0005</employeeId> + <name>Robert Myers</name> + <position>Computer Specialist</position> + <salary>90,000</salary> + <gender>male</gender> + <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address> + </employee> + </staff> diff --git a/xml/src/test/resources/out_dh/staff.out b/xml/src/test/resources/out_dh/staff.out new file mode 100644 index 0000000..467fd08 --- /dev/null +++ b/xml/src/test/resources/out_dh/staff.out @@ -0,0 +1,45 @@ +true^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#true^# + + EMP0001 + Margaret Martin + Accountant + 56,000 + Female + 1230 North Ave. Dallas, Texas 98551 + + + EMP0002 + Martha RaynoldsThis is a CDATASection with EntityReference number 2 &ent2; +This is an adjacent CDATASection with a reference to a tab &tab; + Secretary + 35,000 + Female + 1900 Dallas Road Dallas, Texas + 98554 + + + EMP0003 + Roger + Jones + Department Manager + 100,000 + Element data + PO Box 27 Irving, texas 98553 + + + EMP0004 + Jeny Oconnor + Personnel Director + 95,000 + Female + 27 South Road. Dallas, Texas 98556 + + + EMP0005 + Robert Myers + Computer Specialist + 90,000 + male + 1821 Nordic. Road, Irving Texas 98558 + + ####$employeeId$employeeId^$name$name^$position$position^$salary$salary^$gender$gender^$address$address^$employee$employee^$employeeId$employeeId^$name$name^$position$position^$salary$salary^$gender$gender^$address$address^$employee$employee^$employeeId$employeeId^$name$name^$position$position^$salary$salary^$entElement$entElement^$gender$gender^$address$address^$employee$employee^$employeeId$employeeId^$name$name^$position$position^$salary$salary^$gender$gender^$address$address^$employee$employee^$employeeId$employeeId^$name$name^$position$position^$salary$salary^$gender$gender^$address$address^$employee$employee^$staff$staff^##TEST-STYLE$PIDATA^PItarget$PIdata^##$staff$staff$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$address$address$domestic$Yes$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$address$address$domestic$Yes$street$Yes$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$entElement$entElement$domestic$Yes$address$address$domestic$Yes$street$No$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$address$address$domestic$Yes$street$Yes$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$address$address$street$Yes## diff --git a/xml/src/test/resources/out_hb/staff.out b/xml/src/test/resources/out_hb/staff.out new file mode 100644 index 0000000..c6d61ad --- /dev/null +++ b/xml/src/test/resources/out_hb/staff.out @@ -0,0 +1,45 @@ +true^#true^# + + EMP0001 + Margaret Martin + Accountant + 56,000 + Female + 1230 North Ave. Dallas, Texas 98551 + + + EMP0002 + Martha RaynoldsThis is a CDATASection with EntityReference number 2 &ent2; +This is an adjacent CDATASection with a reference to a tab &tab; + Secretary + 35,000 + Female + 1900 Dallas Road Dallas, Texas + 98554 + + + EMP0003 + Roger + Jones + Department Manager + 100,000 + Element data + PO Box 27 Irving, texas 98553 + + + EMP0004 + Jeny Oconnor + Personnel Director + 95,000 + Female + 27 South Road. Dallas, Texas 98556 + + + EMP0005 + Robert Myers + Computer Specialist + 90,000 + male + 1821 Nordic. Road, Irving Texas 98558 + + ######TEST-STYLE$PIDATA^PItarget$PIdata^#### diff --git a/xml/src/test/resources/recipe.xml b/xml/src/test/resources/recipe.xml new file mode 100644 index 0000000..d7cf0fb --- /dev/null +++ b/xml/src/test/resources/recipe.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE collection SYSTEM "./recipt.dtd"> +<!--comment1 --> +<collection> + <description> + Some recipes used for the XML tutorial. + </description> + <recipe> + <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title> + <ingredient name="beef cube steak" amount="1.5" unit="pound"/> + <preparation> + <step> + Preheat oven to 350 degrees F (175 degrees C). + </step> + </preparation> + <comment> + Make the meat ahead of time, and refrigerate over night, the acid in the + tomato sauce will tenderize the meat even more. If you do this, save the + mozzarella till the last minute. + </comment> + <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/> + </recipe> +</collection> +<!--comment2 --> diff --git a/xml/src/test/resources/recipe1.xml b/xml/src/test/resources/recipe1.xml new file mode 100644 index 0000000..d7cf0fb --- /dev/null +++ b/xml/src/test/resources/recipe1.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE collection SYSTEM "./recipt.dtd"> +<!--comment1 --> +<collection> + <description> + Some recipes used for the XML tutorial. + </description> + <recipe> + <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title> + <ingredient name="beef cube steak" amount="1.5" unit="pound"/> + <preparation> + <step> + Preheat oven to 350 degrees F (175 degrees C). + </step> + </preparation> + <comment> + Make the meat ahead of time, and refrigerate over night, the acid in the + tomato sauce will tenderize the meat even more. If you do this, save the + mozzarella till the last minute. + </comment> + <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/> + </recipe> +</collection> +<!--comment2 --> diff --git a/xml/src/test/resources/recipt.dtd b/xml/src/test/resources/recipt.dtd new file mode 100644 index 0000000..370112c --- /dev/null +++ b/xml/src/test/resources/recipt.dtd @@ -0,0 +1,17 @@ +<!ELEMENT collection (description,recipe+)> +<!ELEMENT description ANY> +<!ELEMENT recipe (title,ingredient*,preparation,comment?,nutrition)> +<!ELEMENT title (#PCDATA)> +<!ELEMENT ingredient (ingredient*,preparation)?> +<!ATTLIST ingredient name CDATA #REQUIRED + amount CDATA #IMPLIED + unit CDATA #IMPLIED> +<!ELEMENT preparation (step*)> +<!ELEMENT step (#PCDATA)> +<!ELEMENT comment (#PCDATA)> +<!ELEMENT nutrition EMPTY> +<!ATTLIST nutrition protein CDATA #REQUIRED + carbohydrates CDATA #REQUIRED + fat CDATA #REQUIRED + calories CDATA #REQUIRED + alcohol CDATA #IMPLIED> diff --git a/xml/src/test/resources/recipt.xml b/xml/src/test/resources/recipt.xml new file mode 100644 index 0000000..d7cf0fb --- /dev/null +++ b/xml/src/test/resources/recipt.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE collection SYSTEM "./recipt.dtd"> +<!--comment1 --> +<collection> + <description> + Some recipes used for the XML tutorial. + </description> + <recipe> + <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title> + <ingredient name="beef cube steak" amount="1.5" unit="pound"/> + <preparation> + <step> + Preheat oven to 350 degrees F (175 degrees C). + </step> + </preparation> + <comment> + Make the meat ahead of time, and refrigerate over night, the acid in the + tomato sauce will tenderize the meat even more. If you do this, save the + mozzarella till the last minute. + </comment> + <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/> + </recipe> +</collection> +<!--comment2 --> diff --git a/xml/src/test/resources/reciptWrong.xml b/xml/src/test/resources/reciptWrong.xml new file mode 100644 index 0000000..ce32d09 --- /dev/null +++ b/xml/src/test/resources/reciptWrong.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE collection SYSTEM "./recipt.dtd"> +<!--comment1 --> +<collection> + <recipe> + <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title> + <ingredient name="beef cube steak" amount="1.5" unit="pound"/> + <preparation> + <step> + Preheat oven to 350 degrees F (175 degrees C). + </step> + </preparation> + <comment> + Make the meat ahead of time, and refrigerate over night, the acid in the + tomato sauce will tenderize the meat even more. If you do this, save the + mozzarella till the last minute. + </comment> + <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/> + </recipe> +</collection> +<!--comment2 --> diff --git a/xml/src/test/resources/simple.xml b/xml/src/test/resources/simple.xml new file mode 100644 index 0000000..de39181 --- /dev/null +++ b/xml/src/test/resources/simple.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- Edited with XML Spy v2007 (http://www.altova.com) --> +<breakfast_menu> + <food> + <name>Belgian Waffles</name> + <price>$5.95</price> + <description>two of our famous Belgian Waffles with plenty of real maple syrup</description> + <calories>650</calories> + </food> + <food> + <name>Strawberry Belgian Waffles</name> + <price>$7.95</price> + <description>light Belgian waffles covered with strawberries and whipped cream</description> + <calories>900</calories> + </food> + <food> + <name>Berry-Berry Belgian Waffles</name> + <price>$8.95</price> + <description>light Belgian waffles covered with an assortment of fresh berries and whipped cream</description> + <calories>900</calories> + </food> + <food> + <name>French Toast</name> + <price>$4.50</price> + <description>thick slices made from our homemade sourdough bread</description> + <calories>600</calories> + </food> + <food> + <name>Homestyle Breakfast</name> + <price>$6.95</price> + <description>two eggs, bacon or sausage, toast, and our ever-popular hash browns</description> + <calories>950</calories> + </food> +</breakfast_menu> diff --git a/xml/src/test/resources/simple_ns.dtd b/xml/src/test/resources/simple_ns.dtd new file mode 100644 index 0000000..7643773 --- /dev/null +++ b/xml/src/test/resources/simple_ns.dtd @@ -0,0 +1,45 @@ +<!ELEMENT staff (employee+,emp:employee,employee) > +<!ELEMENT employee (employeeId,name,position,salary,gender,address) > +<!ATTLIST employee xmlns CDATA #IMPLIED> +<!ATTLIST employee xmlns:dmstc CDATA #IMPLIED> +<!ATTLIST employee xmlns:emp2 CDATA #IMPLIED> + +<!ELEMENT employeeId (#PCDATA) > + +<!ELEMENT name (#PCDATA) > + +<!ELEMENT position (#PCDATA) > + +<!ELEMENT salary (#PCDATA) > + +<!ELEMENT entElement1 (#PCDATA) > +<!ELEMENT gender (#PCDATA | entElement1)* > +<!ATTLIST entElement1 xmlns:local1 CDATA #IMPLIED > + +<!ELEMENT address (#PCDATA) > +<!ATTLIST address dmstc:domestic CDATA #IMPLIED> +<!ATTLIST address street CDATA #IMPLIED> +<!ATTLIST address domestic CDATA #IMPLIED> +<!ATTLIST address xmlns CDATA #IMPLIED> + +<!ELEMENT emp:employee (emp:employeeId,nm:name,emp:position,emp:salary,emp:gender,emp:address) > +<!ATTLIST emp:employee xmlns:emp CDATA #IMPLIED> +<!ATTLIST emp:employee xmlns:nm CDATA #IMPLIED> +<!ATTLIST emp:employee defaultAttr CDATA 'defaultVal'> + +<!ELEMENT emp:employeeId (#PCDATA) > + +<!ELEMENT nm:name (#PCDATA) > + +<!ELEMENT emp:position (#PCDATA) > + +<!ELEMENT emp:salary (#PCDATA) > + +<!ELEMENT emp:gender (#PCDATA) > + +<!ELEMENT emp:address (#PCDATA) > +<!ATTLIST emp:address emp:domestic CDATA #IMPLIED> +<!ATTLIST emp:address street CDATA #IMPLIED> +<!ATTLIST emp:address emp:zone ID #IMPLIED> +<!ATTLIST emp:address emp:district CDATA 'DISTRICT'> +<!ATTLIST emp:address emp:local1 CDATA 'FALSE'> diff --git a/xml/src/test/resources/simple_ns.xml b/xml/src/test/resources/simple_ns.xml new file mode 100644 index 0000000..a5dc4a3 --- /dev/null +++ b/xml/src/test/resources/simple_ns.xml @@ -0,0 +1,59 @@ +<?xml version="1.0"?><?TEST-STYLE PIDATA?> +<!DOCTYPE staff PUBLIC "STAFF" "simple_ns.dtd" +[ + <!ENTITY ent1 "es"> + <!ENTITY ent2 "1900 Dallas Road"> + <!ENTITY ent3 "Texas"> + <!ENTITY ent4 "<entElement1 xmlns:local1='www.xyz.com'>Element data</entElement1><?PItarget PIdata?>"> + <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1> + <!ENTITY ent6 PUBLIC "uri" "file" NDATA notation2> + <!ENTITY ent1 "This entity should be discarded"> + <!NOTATION notation1 PUBLIC "notation1File"> + <!NOTATION notation2 SYSTEM "notation2File"> +]> +<!-- This is comment number 1.--> +<staff> + <employee xmlns="http://www.nist.gov" xmlns:dmstc="http://www.usa.com"> + <employeeId>EMP0001</employeeId> + <name>Margaret Martin</name> + <position>Accountant</position> + <salary>56,000</salary> + <gender>Female</gender> + <address dmstc:domestic="Yes">1230 North Ave. Dallas, Texas 98551</address> + </employee> + <employee xmlns:dmstc="http://www.usa.com"> + <employeeId>EMP0002</employeeId> + <name>Martha Raynolds +<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]> +<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name> + <position>Secretary</position> + <salary>35,000</salary> + <gender>Female</gender> + <address dmstc:domestic="Yes" street="Yes">&ent2; Dallas, &ent3; + 98554</address> + </employee> + <employee xmlns:dmstc="http://www.netzero.com"> + <employeeId>EMP0003</employeeId> + <name>Roger + Jones</name> + <position>Department Manager</position> + <salary>100,000</salary> + <gender>&ent4;</gender> + <address dmstc:domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address> + </employee> + <emp:employee xmlns:emp="http://www.nist.gov" xmlns:nm="http://www.altavista.com" > <emp:employeeId>EMP0004</emp:employeeId> + <nm:name>Jeny Oconnor</nm:name> + <emp:position>Personnel Director</emp:position> + <emp:salary>95,000</emp:salary> + <emp:gender>Female</emp:gender> + <emp:address emp:domestic="Yes" street="Y&ent1;" emp:zone="CANADA" emp:local1="TRUE">27 South Road. Dallas, texas 98556</emp:address> + </emp:employee> + <employee xmlns:emp2="http://www.nist.gov"> + <employeeId>EMP0005</employeeId> + <name>Robert Myers</name> + <position>Computer Specialist</position> + <salary>90,000</salary> + <gender>male</gender> + <address street="Yes" xmlns="http://www.nist.gov">1821 Nordic. Road, Irving Texas 98558</address> + </employee> + </staff> diff --git a/xml/src/test/resources/staff.dtd b/xml/src/test/resources/staff.dtd new file mode 100644 index 0000000..02a994d --- /dev/null +++ b/xml/src/test/resources/staff.dtd @@ -0,0 +1,17 @@ +<!ELEMENT employeeId (#PCDATA)> +<!ELEMENT name (#PCDATA)> +<!ELEMENT position (#PCDATA)> +<!ELEMENT salary (#PCDATA)> +<!ELEMENT address (#PCDATA)> +<!ELEMENT entElement ( #PCDATA ) > +<!ELEMENT gender ( #PCDATA | entElement )* > +<!ELEMENT employee (employeeId, name, position, salary, gender, address) > +<!ELEMENT staff (employee)+> +<!ATTLIST entElement + attr1 CDATA "Attr"> +<!ATTLIST address + domestic CDATA #IMPLIED + street CDATA "Yes"> +<!ATTLIST entElement + domestic CDATA "MALE" > + diff --git a/xml/src/test/resources/staff.xml b/xml/src/test/resources/staff.xml new file mode 100644 index 0000000..f89c510 --- /dev/null +++ b/xml/src/test/resources/staff.xml @@ -0,0 +1,57 @@ +<?xml version="1.0"?><?TEST-STYLE PIDATA?> +<!DOCTYPE staff SYSTEM "staff.dtd" [ + <!ENTITY ent1 "es"> + <!ENTITY ent2 "1900 Dallas Road"> + <!ENTITY ent3 "Texas"> + <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>"> + <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1> + <!ENTITY ent1 "This entity should be discarded"> + <!NOTATION notation1 PUBLIC "notation1File"> + <!NOTATION notation2 SYSTEM "notation2File"> +]> +<!-- This is comment number 1.--> +<staff> + <employee> + <employeeId>EMP0001</employeeId> + <name>Margaret Martin</name> + <position>Accountant</position> + <salary>56,000</salary> + <gender>Female</gender> + <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address> + </employee> + <employee> + <employeeId>EMP0002</employeeId> + <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]> +<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name> + <position>Secretary</position> + <salary>35,000</salary> + <gender>Female</gender> + <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3; + 98554</address> + </employee> + <employee> + <employeeId>EMP0003</employeeId> + <name>Roger + Jones</name> + <position>Department Manager</position> + <salary>100,000</salary> + <gender>&ent4;</gender> + <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address> + </employee> + <employee> + <employeeId>EMP0004</employeeId> + <name>Jeny Oconnor</name> + <position>Personnel Director</position> + <salary>95,000</salary> + <gender>Female</gender> + <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address> + </employee> + <employee> + <employeeId>EMP0005</employeeId> + <name>Robert Myers</name> + <position>Computer Specialist</position> + <salary>90,000</salary> + <gender>male</gender> + <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address> + </employee> + </staff> diff --git a/xml/src/test/resources/staff2.dtd b/xml/src/test/resources/staff2.dtd new file mode 100644 index 0000000..0bac8f2 --- /dev/null +++ b/xml/src/test/resources/staff2.dtd @@ -0,0 +1,24 @@ +<!ELEMENT employeeId (#PCDATA)> +<!ELEMENT name (#PCDATA)> +<!ELEMENT position (#PCDATA)> +<!ELEMENT salary (#PCDATA)> +<!ELEMENT address (#PCDATA)> +<!ELEMENT gender ( #PCDATA)> +<!ELEMENT employee (employeeId, name, position, salary, gender, address) > +<!ATTLIST employee xmlns CDATA #IMPLIED> +<!ELEMENT staff (employee)+> +<!ELEMENT svg (rect, script, employee+)> +<!ATTLIST svg + xmlns CDATA #FIXED "http://www.w3.org/2000/svg" + name CDATA #IMPLIED> +<!ELEMENT rect EMPTY> +<!ATTLIST rect + x CDATA #REQUIRED + y CDATA #REQUIRED + width CDATA #REQUIRED + height CDATA #REQUIRED> +<!ELEMENT script (#PCDATA)> +<!ATTLIST script type CDATA #IMPLIED> +<!ENTITY svgunit SYSTEM "svgunit.js"> +<!ENTITY svgtest SYSTEM "internalSubset01.js"> + diff --git a/xml/src/test/resources/staff2.xml b/xml/src/test/resources/staff2.xml new file mode 100644 index 0000000..d3d9a13 --- /dev/null +++ b/xml/src/test/resources/staff2.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?><?TEST-STYLE PIDATA?> +<!DOCTYPE staff SYSTEM "staff2.dtd" []> +<!-- This is comment number 1.--> +<staff> + <employee> + <employeeId>EMP0001</employeeId> + <name>Margaret Martin</name> + <position>Accountant</position> + <salary>56,000</salary> + <gender>Female</gender> + <address>1230 North Ave. Dallas, Texas 98551</address> + </employee> + </staff> diff --git a/xml/src/test/resources/staffEntRes.xml b/xml/src/test/resources/staffEntRes.xml new file mode 100644 index 0000000..0c24c83 --- /dev/null +++ b/xml/src/test/resources/staffEntRes.xml @@ -0,0 +1,60 @@ +<?xml version="1.0"?><?TEST-STYLE PIDATA?> +<!DOCTYPE staff +[ + <!ENTITY ent1 "es"> + <!ENTITY ent2 "1900 Dallas Road"> + <!ENTITY ent3 "Texas"> + <!ENTITY chap1 SYSTEM "chap1.xml"> + <!ENTITY ent4 "<entElement1 xmlns:local1='www.xyz.com'>Element data</entElement1><?PItarget PIdata?>"> + <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1> + <!ENTITY ent6 PUBLIC "uri" "file" NDATA notation2> + <!ENTITY ent1 "This entity should be discarded"> + <!NOTATION notation1 PUBLIC "notation1File"> + <!NOTATION notation2 SYSTEM "notation2File"> +]> +<!-- This is comment number 1.--> +<staff> + <employee xmlns="http://www.nist.gov" xmlns:dmstc="http://www.usa.com"> + <employeeId>EMP0001</employeeId> + <name>Margaret Martin</name> + <position>Accountant</position> + <salary>56,000</salary> + <gender>Female</gender> + <address dmstc:domestic="Yes">1230 North Ave. Dallas, Texas 98551</address> + </employee> + <employee xmlns:dmstc="http://www.usa.com"> + <employeeId>EMP0002</employeeId> + <name>Martha Raynolds &chap1; +<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]> +<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name> + <position>Secretary</position> + <salary>35,000</salary> + <gender>Female</gender> + <address dmstc:domestic="Yes" street="Yes">&ent2; Dallas, &ent3; + 98554</address> + </employee> + <employee xmlns:dmstc="http://www.netzero.com"> + <employeeId>EMP0003</employeeId> + <name>Roger + Jones</name> + <position>Department Manager</position> + <salary>100,000</salary> + <gender>&ent4;</gender> + <address dmstc:domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address> + </employee> + <emp:employee xmlns:emp="http://www.nist.gov" xmlns:nm="http://www.altavista.com" > <emp:employeeId>EMP0004</emp:employeeId> + <nm:name>Jeny Oconnor</nm:name> + <emp:position>Personnel Director</emp:position> + <emp:salary>95,000</emp:salary> + <emp:gender>Female</emp:gender> + <emp:address emp:domestic="Yes" street="Y&ent1;" emp:zone="CANADA" emp:local1="TRUE">27 South Road. Dallas, texas 98556</emp:address> + </emp:employee> + <employee xmlns:emp2="http://www.nist.gov"> + <employeeId>EMP0005</employeeId> + <name>Robert Myers</name> + <position>Computer Specialist</position> + <salary>90,000</salary> + <gender>male</gender> + <address street="Yes" xmlns="http://www.nist.gov">1821 Nordic. Road, Irving Texas 98558</address> + </employee> + </staff> diff --git a/xml/src/test/resources/staffNS.dtd b/xml/src/test/resources/staffNS.dtd new file mode 100644 index 0000000..7643773 --- /dev/null +++ b/xml/src/test/resources/staffNS.dtd @@ -0,0 +1,45 @@ +<!ELEMENT staff (employee+,emp:employee,employee) > +<!ELEMENT employee (employeeId,name,position,salary,gender,address) > +<!ATTLIST employee xmlns CDATA #IMPLIED> +<!ATTLIST employee xmlns:dmstc CDATA #IMPLIED> +<!ATTLIST employee xmlns:emp2 CDATA #IMPLIED> + +<!ELEMENT employeeId (#PCDATA) > + +<!ELEMENT name (#PCDATA) > + +<!ELEMENT position (#PCDATA) > + +<!ELEMENT salary (#PCDATA) > + +<!ELEMENT entElement1 (#PCDATA) > +<!ELEMENT gender (#PCDATA | entElement1)* > +<!ATTLIST entElement1 xmlns:local1 CDATA #IMPLIED > + +<!ELEMENT address (#PCDATA) > +<!ATTLIST address dmstc:domestic CDATA #IMPLIED> +<!ATTLIST address street CDATA #IMPLIED> +<!ATTLIST address domestic CDATA #IMPLIED> +<!ATTLIST address xmlns CDATA #IMPLIED> + +<!ELEMENT emp:employee (emp:employeeId,nm:name,emp:position,emp:salary,emp:gender,emp:address) > +<!ATTLIST emp:employee xmlns:emp CDATA #IMPLIED> +<!ATTLIST emp:employee xmlns:nm CDATA #IMPLIED> +<!ATTLIST emp:employee defaultAttr CDATA 'defaultVal'> + +<!ELEMENT emp:employeeId (#PCDATA) > + +<!ELEMENT nm:name (#PCDATA) > + +<!ELEMENT emp:position (#PCDATA) > + +<!ELEMENT emp:salary (#PCDATA) > + +<!ELEMENT emp:gender (#PCDATA) > + +<!ELEMENT emp:address (#PCDATA) > +<!ATTLIST emp:address emp:domestic CDATA #IMPLIED> +<!ATTLIST emp:address street CDATA #IMPLIED> +<!ATTLIST emp:address emp:zone ID #IMPLIED> +<!ATTLIST emp:address emp:district CDATA 'DISTRICT'> +<!ATTLIST emp:address emp:local1 CDATA 'FALSE'> diff --git a/xml/src/test/resources/staffNS.xml b/xml/src/test/resources/staffNS.xml new file mode 100644 index 0000000..1cb1459 --- /dev/null +++ b/xml/src/test/resources/staffNS.xml @@ -0,0 +1,59 @@ +<?xml version="1.0"?><?TEST-STYLE PIDATA?> +<!DOCTYPE staff PUBLIC "STAFF" "staffNS.dtd" +[ + <!ENTITY ent1 "es"> + <!ENTITY ent2 "1900 Dallas Road"> + <!ENTITY ent3 "Texas"> + <!ENTITY ent4 "<entElement1 xmlns:local1='www.xyz.com'>Element data</entElement1><?PItarget PIdata?>"> + <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1> + <!ENTITY ent6 PUBLIC "uri" "file" NDATA notation2> + <!ENTITY ent1 "This entity should be discarded"> + <!NOTATION notation1 PUBLIC "notation1File"> + <!NOTATION notation2 SYSTEM "notation2File"> +]> +<!-- This is comment number 1.--> +<staff> + <employee xmlns="http://www.nist.gov" xmlns:dmstc="http://www.usa.com"> + <employeeId>EMP0001</employeeId> + <name>Margaret Martin</name> + <position>Accountant</position> + <salary>56,000</salary> + <gender>Female</gender> + <address dmstc:domestic="Yes">1230 North Ave. Dallas, Texas 98551</address> + </employee> + <employee xmlns:dmstc="http://www.usa.com"> + <employeeId>EMP0002</employeeId> + <name>Martha Raynolds +<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]> +<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name> + <position>Secretary</position> + <salary>35,000</salary> + <gender>Female</gender> + <address dmstc:domestic="Yes" street="Yes">&ent2; Dallas, &ent3; + 98554</address> + </employee> + <employee xmlns:dmstc="http://www.netzero.com"> + <employeeId>EMP0003</employeeId> + <name>Roger + Jones</name> + <position>Department Manager</position> + <salary>100,000</salary> + <gender>&ent4;</gender> + <address dmstc:domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address> + </employee> + <emp:employee xmlns:emp="http://www.nist.gov" xmlns:nm="http://www.altavista.com" > <emp:employeeId>EMP0004</emp:employeeId> + <nm:name>Jeny Oconnor</nm:name> + <emp:position>Personnel Director</emp:position> + <emp:salary>95,000</emp:salary> + <emp:gender>Female</emp:gender> + <emp:address emp:domestic="Yes" street="Y&ent1;" emp:zone="CANADA" emp:local1="TRUE">27 South Road. Dallas, texas 98556</emp:address> + </emp:employee> + <employee xmlns:emp2="http://www.nist.gov"> + <employeeId>EMP0005</employeeId> + <name>Robert Myers</name> + <position>Computer Specialist</position> + <salary>90,000</salary> + <gender>male</gender> + <address street="Yes" xmlns="http://www.nist.gov">1821 Nordic. Road, Irving Texas 98558</address> + </employee> + </staff> diff --git a/xml/src/test/resources/systemid.xml b/xml/src/test/resources/systemid.xml new file mode 100644 index 0000000..d7cf0fb --- /dev/null +++ b/xml/src/test/resources/systemid.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE collection SYSTEM "./recipt.dtd"> +<!--comment1 --> +<collection> + <description> + Some recipes used for the XML tutorial. + </description> + <recipe> + <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title> + <ingredient name="beef cube steak" amount="1.5" unit="pound"/> + <preparation> + <step> + Preheat oven to 350 degrees F (175 degrees C). + </step> + </preparation> + <comment> + Make the meat ahead of time, and refrigerate over night, the acid in the + tomato sauce will tenderize the meat even more. If you do this, save the + mozzarella till the last minute. + </comment> + <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/> + </recipe> +</collection> +<!--comment2 --> diff --git a/xml/src/test/resources/systemid/recipt.dtd b/xml/src/test/resources/systemid/recipt.dtd new file mode 100644 index 0000000..370112c --- /dev/null +++ b/xml/src/test/resources/systemid/recipt.dtd @@ -0,0 +1,17 @@ +<!ELEMENT collection (description,recipe+)> +<!ELEMENT description ANY> +<!ELEMENT recipe (title,ingredient*,preparation,comment?,nutrition)> +<!ELEMENT title (#PCDATA)> +<!ELEMENT ingredient (ingredient*,preparation)?> +<!ATTLIST ingredient name CDATA #REQUIRED + amount CDATA #IMPLIED + unit CDATA #IMPLIED> +<!ELEMENT preparation (step*)> +<!ELEMENT step (#PCDATA)> +<!ELEMENT comment (#PCDATA)> +<!ELEMENT nutrition EMPTY> +<!ATTLIST nutrition protein CDATA #REQUIRED + carbohydrates CDATA #REQUIRED + fat CDATA #REQUIRED + calories CDATA #REQUIRED + alcohol CDATA #IMPLIED> diff --git a/xml/src/test/resources/systemid/staff.dtd b/xml/src/test/resources/systemid/staff.dtd new file mode 100644 index 0000000..02a994d --- /dev/null +++ b/xml/src/test/resources/systemid/staff.dtd @@ -0,0 +1,17 @@ +<!ELEMENT employeeId (#PCDATA)> +<!ELEMENT name (#PCDATA)> +<!ELEMENT position (#PCDATA)> +<!ELEMENT salary (#PCDATA)> +<!ELEMENT address (#PCDATA)> +<!ELEMENT entElement ( #PCDATA ) > +<!ELEMENT gender ( #PCDATA | entElement )* > +<!ELEMENT employee (employeeId, name, position, salary, gender, address) > +<!ELEMENT staff (employee)+> +<!ATTLIST entElement + attr1 CDATA "Attr"> +<!ATTLIST address + domestic CDATA #IMPLIED + street CDATA "Yes"> +<!ATTLIST entElement + domestic CDATA "MALE" > + diff --git a/xml/src/test/resources/wf/staff.dtd b/xml/src/test/resources/wf/staff.dtd new file mode 100644 index 0000000..02a994d --- /dev/null +++ b/xml/src/test/resources/wf/staff.dtd @@ -0,0 +1,17 @@ +<!ELEMENT employeeId (#PCDATA)> +<!ELEMENT name (#PCDATA)> +<!ELEMENT position (#PCDATA)> +<!ELEMENT salary (#PCDATA)> +<!ELEMENT address (#PCDATA)> +<!ELEMENT entElement ( #PCDATA ) > +<!ELEMENT gender ( #PCDATA | entElement )* > +<!ELEMENT employee (employeeId, name, position, salary, gender, address) > +<!ELEMENT staff (employee)+> +<!ATTLIST entElement + attr1 CDATA "Attr"> +<!ATTLIST address + domestic CDATA #IMPLIED + street CDATA "Yes"> +<!ATTLIST entElement + domestic CDATA "MALE" > + diff --git a/xml/src/test/resources/wf/staff.xml b/xml/src/test/resources/wf/staff.xml new file mode 100644 index 0000000..f89c510 --- /dev/null +++ b/xml/src/test/resources/wf/staff.xml @@ -0,0 +1,57 @@ +<?xml version="1.0"?><?TEST-STYLE PIDATA?> +<!DOCTYPE staff SYSTEM "staff.dtd" [ + <!ENTITY ent1 "es"> + <!ENTITY ent2 "1900 Dallas Road"> + <!ENTITY ent3 "Texas"> + <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>"> + <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1> + <!ENTITY ent1 "This entity should be discarded"> + <!NOTATION notation1 PUBLIC "notation1File"> + <!NOTATION notation2 SYSTEM "notation2File"> +]> +<!-- This is comment number 1.--> +<staff> + <employee> + <employeeId>EMP0001</employeeId> + <name>Margaret Martin</name> + <position>Accountant</position> + <salary>56,000</salary> + <gender>Female</gender> + <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address> + </employee> + <employee> + <employeeId>EMP0002</employeeId> + <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]> +<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name> + <position>Secretary</position> + <salary>35,000</salary> + <gender>Female</gender> + <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3; + 98554</address> + </employee> + <employee> + <employeeId>EMP0003</employeeId> + <name>Roger + Jones</name> + <position>Department Manager</position> + <salary>100,000</salary> + <gender>&ent4;</gender> + <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address> + </employee> + <employee> + <employeeId>EMP0004</employeeId> + <name>Jeny Oconnor</name> + <position>Personnel Director</position> + <salary>95,000</salary> + <gender>Female</gender> + <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address> + </employee> + <employee> + <employeeId>EMP0005</employeeId> + <name>Robert Myers</name> + <position>Computer Specialist</position> + <salary>90,000</salary> + <gender>male</gender> + <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address> + </employee> + </staff> diff --git a/xml/src/test/resources/wrong.xml b/xml/src/test/resources/wrong.xml new file mode 100644 index 0000000..9d4b41d --- /dev/null +++ b/xml/src/test/resources/wrong.xml @@ -0,0 +1 @@ +<wrong1>wrong</wrong2>
\ No newline at end of file diff --git a/xml/src/test/resources/xhtml1-strict.dtd b/xml/src/test/resources/xhtml1-strict.dtd new file mode 100644 index 0000000..60bbaf7 --- /dev/null +++ b/xml/src/test/resources/xhtml1-strict.dtd @@ -0,0 +1,65 @@ +<!-- + +Copyright (c) 2001-2004 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All +Rights Reserved. This program is distributed under the W3C's Software +Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details. + +--> + +<!-- + +This is a radically simplified DTD for use in the DOM Test Suites +due to a XML non-conformance of one implementation in processing +parameter entities. When that non-conformance is resolved, +this DTD can be replaced by the normal DTD for XHTML. + +--> + + +<!ELEMENT html (head, body)> +<!ATTLIST html xmlns CDATA #IMPLIED> +<!ELEMENT head (meta,title,script*)> +<!ELEMENT meta EMPTY> +<!ATTLIST meta + http-equiv CDATA #IMPLIED + content CDATA #IMPLIED> +<!ELEMENT title (#PCDATA)> +<!ELEMENT body (p*)> +<!ATTLIST body onload CDATA #IMPLIED> +<!ELEMENT p (#PCDATA|em|strong|code|sup|var|acronym|abbr)*> +<!ATTLIST p + xmlns:dmstc CDATA #IMPLIED + xmlns:nm CDATA #IMPLIED + xmlns:emp2 CDATA #IMPLIED + id ID #IMPLIED +> +<!ELEMENT em (#PCDATA)> +<!ELEMENT span (#PCDATA)> +<!ELEMENT strong (#PCDATA)> +<!ELEMENT code (#PCDATA)> +<!ELEMENT sup (#PCDATA)> +<!ELEMENT var (#PCDATA|span)*> +<!ELEMENT acronym (#PCDATA)> +<!ATTLIST acronym + title CDATA #IMPLIED + class CDATA #IMPLIED + id ID #IMPLIED +> +<!ELEMENT abbr (#PCDATA)> +<!ATTLIST abbr + title CDATA #IMPLIED + class CDATA #IMPLIED + id ID #IMPLIED +> +<!ELEMENT script (#PCDATA)> +<!ATTLIST script + type CDATA #IMPLIED + src CDATA #IMPLIED + charset CDATA #IMPLIED> |