diff --git a/eng/versioning/version_client.txt b/eng/versioning/version_client.txt
index 6cc95f5ff643..a8d752c26707 100644
--- a/eng/versioning/version_client.txt
+++ b/eng/versioning/version_client.txt
@@ -461,6 +461,8 @@ com.azure.tools:azure-sdk-build-tool;1.0.0;1.1.0-beta.1
# In the pom, the version update tag after the version should name the unreleased package and the dependency version:
#
+unreleased_com.azure:azure-xml;1.0.0-beta.4
+unreleased_com.azure:azure-core;1.48.0-beta.1
# Released Beta dependencies: Copy the entry from above, prepend "beta_", remove the current
# version and set the version to the released beta. Released beta dependencies are only valid
diff --git a/sdk/core/azure-core-experimental/pom.xml b/sdk/core/azure-core-experimental/pom.xml
index 63d4366496fe..b6167dc5caad 100644
--- a/sdk/core/azure-core-experimental/pom.xml
+++ b/sdk/core/azure-core-experimental/pom.xml
@@ -91,7 +91,7 @@
com.azureazure-xml
- 1.0.0-beta.3
+ 1.0.0-beta.4test
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/ReflectionSerializable.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/ReflectionSerializable.java
index fb08375e0630..850161f2a87e 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/ReflectionSerializable.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/ReflectionSerializable.java
@@ -58,17 +58,23 @@ public final class ReflectionSerializable {
try {
xmlSerializable = Class.forName("com.azure.xml.XmlSerializable");
xmlReader = Class.forName("com.azure.xml.XmlReader");
-
- Class> xmlProviders = Class.forName("com.azure.xml.XmlProviders");
-
- xmlReaderCreator = ReflectionUtils.getMethodInvoker(xmlProviders,
- xmlProviders.getDeclaredMethod("createReader", byte[].class));
-
- xmlWriterCreator = ReflectionUtils.getMethodInvoker(xmlProviders,
- xmlProviders.getDeclaredMethod("createWriter", OutputStream.class));
-
Class> xmlWriter = Class.forName("com.azure.xml.XmlWriter");
+ try {
+ Class> xmlProviders = Class.forName("com.azure.xml.XmlProviders");
+
+ xmlReaderCreator = ReflectionUtils.getMethodInvoker(xmlProviders,
+ xmlProviders.getDeclaredMethod("createReader", byte[].class));
+
+ xmlWriterCreator = ReflectionUtils.getMethodInvoker(xmlProviders,
+ xmlProviders.getDeclaredMethod("createWriter", OutputStream.class));
+ } catch (LinkageError | ReflectiveOperationException ex) {
+ xmlReaderCreator = ReflectionUtils.getMethodInvoker(xmlReader,
+ xmlReader.getDeclaredMethod("fromBytes", byte[].class));
+ xmlWriterCreator = ReflectionUtils.getMethodInvoker(xmlWriter,
+ xmlWriter.getDeclaredMethod("toStream", OutputStream.class));
+ }
+
xmlWriterWriteStartDocument
= ReflectionUtils.getMethodInvoker(xmlWriter, xmlWriter.getDeclaredMethod("writeStartDocument"));
diff --git a/sdk/serialization/azure-json/src/main/java/com/azure/json/implementation/DefaultJsonProvider.java b/sdk/serialization/azure-json/src/main/java/com/azure/json/implementation/DefaultJsonProvider.java
index db5a115fbccb..42043ef667df 100644
--- a/sdk/serialization/azure-json/src/main/java/com/azure/json/implementation/DefaultJsonProvider.java
+++ b/sdk/serialization/azure-json/src/main/java/com/azure/json/implementation/DefaultJsonProvider.java
@@ -19,10 +19,10 @@
*/
public final class DefaultJsonProvider implements JsonProvider {
private static final String JSON_READER_EXCEPTION
- = "Both 'json' and 'options' must be passed as non-null to " + "create an instance of JsonReader.";
+ = "Both 'json' and 'options' must be passed as non-null to create an instance of JsonReader.";
private static final String JSON_WRITER_EXCEPTION
- = "Both 'json' and 'options' must be passed as non-null to " + "create an instance of JsonWriter.";
+ = "Both 'json' and 'options' must be passed as non-null to create an instance of JsonWriter.";
@Override
public JsonReader createReader(byte[] json, JsonOptions options) throws IOException {
diff --git a/sdk/serialization/azure-xml/spotbugs-exclude.xml b/sdk/serialization/azure-xml/spotbugs-exclude.xml
index da8e297c72ef..e6c43c2c787e 100644
--- a/sdk/serialization/azure-xml/spotbugs-exclude.xml
+++ b/sdk/serialization/azure-xml/spotbugs-exclude.xml
@@ -4,6 +4,6 @@
xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd">
-
+
diff --git a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlProvider.java b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlProvider.java
deleted file mode 100644
index 2ac963aba598..000000000000
--- a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlProvider.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.xml;
-
-import javax.xml.stream.XMLStreamException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-
-/**
- * An interface to be implemented by any azure-xml plugin that wishes to provide an alternate {@link XmlReader} or
- * {@link XmlWriter} implementation.
- */
-public interface XmlProvider {
- /**
- * Creates an instance of {@link XmlReader} that reads a {@code byte[]}.
- *
- * @param json The JSON represented as a {@code byte[]}.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code json} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- XmlReader createReader(byte[] json) throws XMLStreamException;
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link String}.
- *
- * @param json The JSON represented as a {@link String}.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code json} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- XmlReader createReader(String json) throws XMLStreamException;
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link InputStream}.
- *
- * @param json The JSON represented as a {@link InputStream}.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code json} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- XmlReader createReader(InputStream json) throws XMLStreamException;
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link Reader}.
- *
- * @param json The JSON represented as a {@link Reader}.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code json} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- XmlReader createReader(Reader json) throws XMLStreamException;
-
- /**
- * Creates an instance of {@link XmlWriter} that writes to an {@link OutputStream}.
- *
- * @param json The JSON represented as an {@link OutputStream}.
- * @return A new instance of {@link XmlWriter}.
- * @throws NullPointerException If {@code json} is null.
- * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
- */
- XmlWriter createWriter(OutputStream json) throws XMLStreamException;
-
- /**
- * Creates an instance of {@link XmlWriter} that writes to an {@link Writer}.
- *
- * @param json The JSON represented as an {@link Writer}.
- * @return A new instance of {@link XmlWriter}.
- * @throws NullPointerException If {@code json} is null.
- * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
- */
- XmlWriter createWriter(Writer json) throws XMLStreamException;
-}
diff --git a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlProviders.java b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlProviders.java
deleted file mode 100644
index 29c98ed58bc1..000000000000
--- a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlProviders.java
+++ /dev/null
@@ -1,273 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.xml;
-
-import com.azure.xml.implementation.DefaultXmlReader;
-import com.azure.xml.implementation.DefaultXmlWriter;
-
-import javax.xml.stream.XMLStreamException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.Iterator;
-import java.util.ServiceLoader;
-
-/**
- * Handles loading an instance of {@link XmlProvider} found on the classpath.
- */
-public final class XmlProviders {
- private static final String CANNOT_FIND_XML = "A request was made to load an XmlReader and XmlWriter provider "
- + "but one could not be found on the classpath. If you are using a dependency manager, consider including a "
- + "dependency that supplies a provider for XmlProvider or indicate to the loader to fallback to the default "
- + "implementation. Additionally, refer to https://aka.ms/azsdk/java/docs/custom-xml to learn about writing "
- + "your own implementation.";
-
- private static XmlProvider defaultProvider;
-
- static {
- // Use as classloader to load provider-configuration files and provider classes the classloader
- // that loaded this class. In most cases this will be the System classloader.
- // But this choice here provides additional flexibility in managed environments that control
- // classloading differently (OSGi, Spring and others) and don't depend on the
- // System classloader to load HttpClientProvider classes.
- ServiceLoader serviceLoader
- = ServiceLoader.load(XmlProvider.class, XmlProvider.class.getClassLoader());
- // Use the first provider found in the service loader iterator.
- Iterator it = serviceLoader.iterator();
- if (it.hasNext()) {
- defaultProvider = it.next();
- }
-
- while (it.hasNext()) {
- it.next();
- }
- }
-
- private XmlProviders() {
- // no-op
- }
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@code byte[]}.
- *
- * If a provider could not be found on the classpath this will use the default implementation, effectively the
- * equivalent to {@link #createReader(byte[], boolean) createReader(xml, true)}.
- *
- * @param xml The XML represented as a {@code byte[]}.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader createReader(byte[] xml) throws XMLStreamException {
- return createReader(xml, true);
- }
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@code byte[]}.
- *
- * @param xml The XML represented as a {@code byte[]}.
- * @param useDefault Whether the default implementation should be used if one could not be found on the classpath.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws IllegalStateException If a provider could not be found on the classpath and {@code useDefault} is false.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader createReader(byte[] xml, boolean useDefault) throws XMLStreamException {
- if (defaultProvider == null) {
- if (useDefault) {
- return DefaultXmlReader.fromBytes(xml);
- } else {
- throw new IllegalStateException(CANNOT_FIND_XML);
- }
- } else {
- return defaultProvider.createReader(xml);
- }
- }
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link String}.
- *
- * If a provider could not be found on the classpath this will use the default implementation, effectively the
- * equivalent to {@link #createReader(String, boolean) createReader(xml, true)}.
- *
- * @param xml The XML represented as a {@link String}.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader createReader(String xml) throws XMLStreamException {
- return createReader(xml, true);
- }
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link String}.
- *
- * @param xml The XML represented as a {@link String}.
- * @param useDefault Whether the default implementation should be used if one could not be found on the classpath.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws IllegalStateException If a provider could not be found on the classpath and {@code useDefault} is false.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader createReader(String xml, boolean useDefault) throws XMLStreamException {
- if (defaultProvider == null) {
- if (useDefault) {
- return DefaultXmlReader.fromString(xml);
- } else {
- throw new IllegalStateException(CANNOT_FIND_XML);
- }
- } else {
- return defaultProvider.createReader(xml);
- }
- }
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link InputStream}.
- *
- * If a provider could not be found on the classpath this will use the default implementation, effectively the
- * equivalent to {@link #createReader(InputStream, boolean) createReader(xml, true)}.
- *
- * @param xml The XML represented as a {@link InputStream}.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader createReader(InputStream xml) throws XMLStreamException {
- return createReader(xml, true);
- }
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link InputStream}.
- *
- * @param xml The XML represented as a {@link InputStream}.
- * @param useDefault Whether the default implementation should be used if one could not be found on the classpath.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws IllegalStateException If a provider could not be found on the classpath and {@code useDefault} is false.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader createReader(InputStream xml, boolean useDefault) throws XMLStreamException {
- if (defaultProvider == null) {
- if (useDefault) {
- return DefaultXmlReader.fromStream(xml);
- } else {
- throw new IllegalStateException(CANNOT_FIND_XML);
- }
- } else {
- return defaultProvider.createReader(xml);
- }
- }
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link Reader}.
- *
- * If a provider could not be found on the classpath this will use the default implementation, effectively the
- * equivalent to {@link #createReader(Reader, boolean) createReader(xml, true)}.
- *
- * @param xml The XML represented as a {@link Reader}.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader createReader(Reader xml) throws XMLStreamException {
- return createReader(xml, true);
- }
-
- /**
- * Creates an instance of {@link XmlReader} that reads a {@link Reader}.
- *
- * @param xml The XML represented as a {@link Reader}.
- * @param useDefault Whether the default implementation should be used if one could not be found on the classpath.
- * @return A new instance of {@link XmlReader}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws IllegalStateException If a provider could not be found on the classpath and {@code useDefault} is false.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader createReader(Reader xml, boolean useDefault) throws XMLStreamException {
- if (defaultProvider == null) {
- if (useDefault) {
- return DefaultXmlReader.fromReader(xml);
- } else {
- throw new IllegalStateException(CANNOT_FIND_XML);
- }
- } else {
- return defaultProvider.createReader(xml);
- }
- }
-
- /**
- * Creates an instance of {@link XmlWriter} that writes to an {@link OutputStream}.
- *
- * If a provider could not be found on the classpath this will use the default implementation, effectively the
- * equivalent to {@link #createWriter(OutputStream, boolean) createWriter(xml, true)}.
- *
- * @param xml The XML represented as an {@link OutputStream}.
- * @return A new instance of {@link XmlWriter}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
- */
- public static XmlWriter createWriter(OutputStream xml) throws XMLStreamException {
- return createWriter(xml, true);
- }
-
- /**
- * Creates an instance of {@link XmlWriter} that writes to an {@link OutputStream}.
- *
- * @param xml The XML represented as an {@link OutputStream}.
- * @param useDefault Whether the default implementation should be used if one could not be found on the classpath.
- * @return A new instance of {@link XmlWriter}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws IllegalStateException If a provider could not be found on the classpath and {@code useDefault} is false.
- * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
- */
- public static XmlWriter createWriter(OutputStream xml, boolean useDefault) throws XMLStreamException {
- if (defaultProvider == null) {
- if (useDefault) {
- return DefaultXmlWriter.toStream(xml);
- } else {
- throw new IllegalStateException(CANNOT_FIND_XML);
- }
- } else {
- return defaultProvider.createWriter(xml);
- }
- }
-
- /**
- * Creates an instance of {@link XmlWriter} that writes to an {@link Writer}.
- *
- * If a provider could not be found on the classpath this will use the default implementation, effectively the
- * equivalent to {@link #createWriter(Writer, boolean) createWriter(xml, true)}.
- *
- * @param xml The XML represented as an {@link Writer}.
- * @return A new instance of {@link XmlWriter}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
- */
- public static XmlWriter createWriter(Writer xml) throws XMLStreamException {
- return createWriter(xml, true);
- }
-
- /**
- * Creates an instance of {@link XmlWriter} that writes to an {@link Writer}.
- *
- * @param xml The XML represented as an {@link Writer}.
- * @param useDefault Whether the default implementation should be used if one could not be found on the classpath.
- * @return A new instance of {@link XmlWriter}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws IllegalStateException If a provider could not be found on the classpath and {@code useDefault} is false.
- * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
- */
- public static XmlWriter createWriter(Writer xml, boolean useDefault) throws XMLStreamException {
- if (defaultProvider == null) {
- if (useDefault) {
- return DefaultXmlWriter.toWriter(xml);
- } else {
- throw new IllegalStateException(CANNOT_FIND_XML);
- }
- } else {
- return defaultProvider.createWriter(xml);
- }
- }
-}
diff --git a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlReader.java b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlReader.java
index 929e00266ec0..247bd898577d 100644
--- a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlReader.java
+++ b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlReader.java
@@ -4,19 +4,121 @@
package com.azure.xml;
import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
import java.util.Base64;
import java.util.Objects;
/**
* Reads an XML encoded value as a stream of tokens.
*/
-public abstract class XmlReader implements AutoCloseable {
+public final class XmlReader implements AutoCloseable {
+ private static final XMLInputFactory XML_INPUT_FACTORY;
+
+ static {
+ XML_INPUT_FACTORY = XMLInputFactory.newInstance();
+ XML_INPUT_FACTORY.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+ XML_INPUT_FACTORY.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+ }
+
+ private final XMLStreamReader reader;
+
+ private XmlToken currentToken;
+
+ /**
+ * Creates an {@link XMLStreamReader}-based {@link XmlReader} that parses the passed {@code xml}.
+ *
+ * This uses the {@link XMLStreamReader} implementation provided by the default
+ * {@link XMLInputFactory#newInstance()}. If you need to provide a custom implementation of
+ * {@link XMLStreamReader} use {@link #fromXmlStreamReader(XMLStreamReader)}.
+ *
+ * @param xml The XML to parse.
+ * @return A new {@link XmlReader} instance.
+ * @throws NullPointerException If {@code xml} is null.
+ * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
+ */
+ public static XmlReader fromBytes(byte[] xml) throws XMLStreamException {
+ Objects.requireNonNull(xml, "'xml' cannot be null.");
+ return fromStream(new ByteArrayInputStream(xml));
+ }
+
+ /**
+ * Creates an {@link XmlReader} that parses the passed {@code xml}.
+ *
+ * This uses the {@link XMLStreamReader} implementation provided by the default
+ * {@link XMLInputFactory#newInstance()}. If you need to provide a custom implementation of
+ * {@link XMLStreamReader} use {@link #fromXmlStreamReader(XMLStreamReader)}.
+ *
+ * @param xml The XML to parse.
+ * @return A new {@link XmlReader} instance.
+ * @throws NullPointerException If {@code xml} is null.
+ * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
+ */
+ public static XmlReader fromString(String xml) throws XMLStreamException {
+ Objects.requireNonNull(xml, "'xml' cannot be null.");
+ return fromReader(new StringReader(xml));
+ }
+
+ /**
+ * Creates an {@link XmlReader} that parses the passed {@code xml}.
+ *
+ * This uses the {@link XMLStreamReader} implementation provided by the default
+ * {@link XMLInputFactory#newInstance()}. If you need to provide a custom implementation of
+ * {@link XMLStreamReader} use {@link #fromXmlStreamReader(XMLStreamReader)}.
+ *
+ * @param xml The XML to parse.
+ * @return A new {@link XmlReader} instance.
+ * @throws NullPointerException If {@code xml} is null.
+ * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
+ */
+ public static XmlReader fromStream(InputStream xml) throws XMLStreamException {
+ Objects.requireNonNull(xml, "'xml' cannot be null.");
+ return new XmlReader(XML_INPUT_FACTORY.createXMLStreamReader(xml));
+ }
+
+ /**
+ * Creates an {@link XmlReader} that parses the passed {@code xml}.
+ *
+ * This uses the {@link XMLStreamReader} implementation provided by the default
+ * {@link XMLInputFactory#newInstance()}. If you need to provide a custom implementation of
+ * {@link XMLStreamReader} use {@link #fromXmlStreamReader(XMLStreamReader)}.
+ *
+ * @param xml The XML to parse.
+ * @return A new {@link XmlReader} instance.
+ * @throws NullPointerException If {@code xml} is null.
+ * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
+ */
+ public static XmlReader fromReader(Reader xml) throws XMLStreamException {
+ Objects.requireNonNull(xml, "'xml' cannot be null.");
+ return new XmlReader(XML_INPUT_FACTORY.createXMLStreamReader(xml));
+ }
+
+ /**
+ * Creates an {@link XmlReader} that parses the passed {@code xml}.
+ *
+ * This uses the provided {@link XMLStreamReader} implementation to parse the XML.
+ *
+ * @param reader The {@link XMLStreamReader} to parse the XML.
+ * @return A new {@link XmlReader} instance.
+ * @throws NullPointerException If {@code reader} is null.
+ */
+ public static XmlReader fromXmlStreamReader(XMLStreamReader reader) {
+ return new XmlReader(reader);
+ }
+
/**
* Creates an instance of {@link XmlReader}.
*/
- public XmlReader() {
+ private XmlReader(XMLStreamReader reader) {
+ this.reader = Objects.requireNonNull(reader, "'reader' cannot be null.");
+ this.currentToken = convertEventToToken(reader.getEventType());
}
/**
@@ -27,7 +129,9 @@ public XmlReader() {
*
* @return The {@link XmlToken} that the reader points to currently.
*/
- public abstract XmlToken currentToken();
+ public XmlToken currentToken() {
+ return currentToken;
+ }
/**
* Iterates to and returns the next {@link XmlToken#START_ELEMENT} or {@link XmlToken#END_ELEMENT} in the XML
@@ -40,7 +144,17 @@ public XmlReader() {
* {@link XmlToken#END_DOCUMENT} if reading completes.
* @throws XMLStreamException If the next element cannot be determined.
*/
- public abstract XmlToken nextElement() throws XMLStreamException;
+ public XmlToken nextElement() throws XMLStreamException {
+ int next = reader.next();
+ while (next != XMLStreamConstants.START_ELEMENT
+ && next != XMLStreamConstants.END_ELEMENT
+ && next != XMLStreamConstants.END_DOCUMENT) {
+ next = reader.next();
+ }
+
+ currentToken = convertEventToToken(next);
+ return currentToken;
+ }
/**
* Closes the XML stream.
@@ -48,7 +162,9 @@ public XmlReader() {
* @throws XMLStreamException If the underlying content store fails to close.
*/
@Override
- public abstract void close() throws XMLStreamException;
+ public void close() throws XMLStreamException {
+ reader.close();
+ }
/**
* Gets the {@link QName} for the current XML element.
@@ -57,7 +173,9 @@ public XmlReader() {
* @throws IllegalStateException If the {@link #currentToken()} {@link XmlToken#START_ELEMENT} or
* {@link XmlToken#END_ELEMENT}.
*/
- public abstract QName getElementName();
+ public QName getElementName() {
+ return reader.getName();
+ }
/**
* Gets the string value for the attribute in the XML element.
@@ -69,7 +187,12 @@ public XmlReader() {
* @return The string value for the attribute in the XML element, or null if the attribute doesn't exist.
* @throws IllegalStateException If {@link #currentToken()} isn't {@link XmlToken#START_ELEMENT}.
*/
- public abstract String getStringAttribute(String namespaceUri, String localName);
+ public String getStringAttribute(String namespaceUri, String localName) {
+ String value = reader.getAttributeValue(namespaceUri, localName);
+
+ // Treat empty string as null.
+ return "".equals(value) ? null : value;
+ }
/**
* Gets the binary value for the attribute in the XML element.
@@ -78,7 +201,7 @@ public XmlReader() {
* @param localName Attribute local name.
* @return The binary value for the attribute in the XML element.
*/
- public final byte[] getBinaryAttribute(String namespaceUri, String localName) {
+ public byte[] getBinaryAttribute(String namespaceUri, String localName) {
String value = getStringAttribute(namespaceUri, localName);
return (value == null || value.isEmpty()) ? null : Base64.getDecoder().decode(value);
}
@@ -90,7 +213,7 @@ public final byte[] getBinaryAttribute(String namespaceUri, String localName) {
* @param localName Attribute local name.
* @return The boolean value for the attribute in the XML element.
*/
- public final boolean getBooleanAttribute(String namespaceUri, String localName) {
+ public boolean getBooleanAttribute(String namespaceUri, String localName) {
return Boolean.parseBoolean(getStringAttribute(namespaceUri, localName));
}
@@ -101,7 +224,7 @@ public final boolean getBooleanAttribute(String namespaceUri, String localName)
* @param localName Attribute local name.
* @return The double value for the attribute in the XML element.
*/
- public final double getDoubleAttribute(String namespaceUri, String localName) {
+ public double getDoubleAttribute(String namespaceUri, String localName) {
return Double.parseDouble(getStringAttribute(namespaceUri, localName));
}
@@ -112,7 +235,7 @@ public final double getDoubleAttribute(String namespaceUri, String localName) {
* @param localName Attribute local name.
* @return The float value for the attribute in the XML element.
*/
- public final float getFloatAttribute(String namespaceUri, String localName) {
+ public float getFloatAttribute(String namespaceUri, String localName) {
return Float.parseFloat(getStringAttribute(namespaceUri, localName));
}
@@ -123,7 +246,7 @@ public final float getFloatAttribute(String namespaceUri, String localName) {
* @param localName Attribute local name.
* @return The int value for the attribute in the XML element.
*/
- public final int getIntAttribute(String namespaceUri, String localName) {
+ public int getIntAttribute(String namespaceUri, String localName) {
return Integer.parseInt(getStringAttribute(namespaceUri, localName));
}
@@ -134,7 +257,7 @@ public final int getIntAttribute(String namespaceUri, String localName) {
* @param localName Attribute local name.
* @return The long value for the attribute in the XML element.
*/
- public final long getLongAttribute(String namespaceUri, String localName) {
+ public long getLongAttribute(String namespaceUri, String localName) {
return Long.parseLong(getStringAttribute(namespaceUri, localName));
}
@@ -151,8 +274,8 @@ public final long getLongAttribute(String namespaceUri, String localName) {
* @return The converted text value, or null if the attribute didn't have a value.
* @throws XMLStreamException If the nullable attribute cannot be read.
*/
- public final T getNullableAttribute(String namespaceUri, String localName,
- ReadValueCallback converter) throws XMLStreamException {
+ public T getNullableAttribute(String namespaceUri, String localName, ReadValueCallback converter)
+ throws XMLStreamException {
String textValue = getStringAttribute(namespaceUri, localName);
if (textValue == null) {
@@ -172,7 +295,72 @@ public final T getNullableAttribute(String namespaceUri, String localName,
* @return The string value for the current element.
* @throws XMLStreamException If the String element cannot be read.
*/
- public abstract String getStringElement() throws XMLStreamException;
+ public String getStringElement() throws XMLStreamException {
+ // The default getElementText implementation in the JDK uses an internal buffer as the API handles merging
+ // multiple text states, characters, CDATA, space, and entity reference, into a single String. This
+ // generally results in overhead as most cases will only have a single read performed but that read will
+ // be buffered into the buffer and then returned as-is. So instead, a custom implementation will be used
+ // where a small String buffer will be used to contain the intermediate reads and when the terminal state
+ // is reached if only a single read was performed the String can be return, and if the unlikely multiple
+ // read scenario is triggered those Strings can be concatenated.
+ //
+ // This logic continues to work even if the underlying XMLStreamReader implementation, such as the one
+ // used in Jackson XML through Woodstox, handles this already.
+
+ int readCount = 0;
+ String firstRead = null;
+ String[] buffer = null;
+ int stringBufferSize = 0;
+ int nextEvent = reader.next();
+
+ // Continue reading until the next event is the end of the element or an exception state.
+ while (nextEvent != XMLStreamConstants.END_ELEMENT) {
+ if (nextEvent == XMLStreamConstants.CHARACTERS
+ || nextEvent == XMLStreamConstants.CDATA
+ || nextEvent == XMLStreamConstants.SPACE
+ || nextEvent == XMLStreamConstants.ENTITY_REFERENCE) {
+ readCount++;
+ if (readCount == 1) {
+ firstRead = reader.getText();
+ stringBufferSize = firstRead.length();
+ } else {
+ if (readCount == 2) {
+ buffer = new String[4];
+ buffer[0] = firstRead;
+ }
+
+ if (readCount > buffer.length - 1) {
+ String[] newBuffer = new String[buffer.length * 2];
+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+ buffer = newBuffer;
+ }
+
+ String readText = reader.getText();
+ buffer[readCount - 1] = readText;
+ stringBufferSize += readText.length();
+ }
+ } else if (nextEvent != XMLStreamConstants.PROCESSING_INSTRUCTION
+ && nextEvent != XMLStreamConstants.COMMENT) {
+ // Processing instructions and comments are ignored but anything else is unexpected.
+ throw new XMLStreamException("Unexpected event type while reading element value " + nextEvent);
+ }
+
+ nextEvent = reader.next();
+ }
+
+ if (readCount == 0) {
+ return null;
+ } else if (readCount == 1) {
+ return firstRead;
+ } else {
+ StringBuilder finalText = new StringBuilder(stringBufferSize);
+ for (int i = 0; i < readCount; i++) {
+ finalText.append(buffer[i]);
+ }
+
+ return finalText.toString();
+ }
+ }
/**
* Gets the binary value for the current element.
@@ -180,7 +368,7 @@ public final T getNullableAttribute(String namespaceUri, String localName,
* @return The binary value for the current element.
* @throws XMLStreamException If the binary element cannot be read.
*/
- public final byte[] getBinaryElement() throws XMLStreamException {
+ public byte[] getBinaryElement() throws XMLStreamException {
String value = getStringElement();
return (value == null || value.isEmpty()) ? null : Base64.getDecoder().decode(value);
}
@@ -191,7 +379,7 @@ public final byte[] getBinaryElement() throws XMLStreamException {
* @return The boolean value for the current element.
* @throws XMLStreamException If the boolean element cannot be read.
*/
- public final boolean getBooleanElement() throws XMLStreamException {
+ public boolean getBooleanElement() throws XMLStreamException {
return Boolean.parseBoolean(getStringElement());
}
@@ -201,7 +389,7 @@ public final boolean getBooleanElement() throws XMLStreamException {
* @return The double value for the current element.
* @throws XMLStreamException If the double element cannot be read.
*/
- public final double getDoubleElement() throws XMLStreamException {
+ public double getDoubleElement() throws XMLStreamException {
return Double.parseDouble(getStringElement());
}
@@ -211,7 +399,7 @@ public final double getDoubleElement() throws XMLStreamException {
* @return The float value for the current element.
* @throws XMLStreamException If the float element cannot be read.
*/
- public final float getFloatElement() throws XMLStreamException {
+ public float getFloatElement() throws XMLStreamException {
return Float.parseFloat(getStringElement());
}
@@ -221,7 +409,7 @@ public final float getFloatElement() throws XMLStreamException {
* @return The int value for the current element.
* @throws XMLStreamException If the int element cannot be read.
*/
- public final int getIntElement() throws XMLStreamException {
+ public int getIntElement() throws XMLStreamException {
return Integer.parseInt(getStringElement());
}
@@ -231,7 +419,7 @@ public final int getIntElement() throws XMLStreamException {
* @return The long value for the current element.
* @throws XMLStreamException If the long element cannot be read.
*/
- public final long getLongElement() throws XMLStreamException {
+ public long getLongElement() throws XMLStreamException {
return Long.parseLong(getStringElement());
}
@@ -246,7 +434,7 @@ public final long getLongElement() throws XMLStreamException {
* @return The converted text value, or null if the element didn't have a value.
* @throws XMLStreamException If the nullable element cannot be read.
*/
- public final T getNullableElement(ReadValueCallback converter) throws XMLStreamException {
+ public T getNullableElement(ReadValueCallback converter) throws XMLStreamException {
String textValue = getStringElement();
if (textValue == null) {
@@ -274,8 +462,7 @@ public final T getNullableElement(ReadValueCallback converter) th
* the expected {@code startTagName}
* @throws XMLStreamException If the object cannot be read.
*/
- public final T readObject(String localName, ReadValueCallback converter)
- throws XMLStreamException {
+ public T readObject(String localName, ReadValueCallback converter) throws XMLStreamException {
return readObject(null, localName, converter);
}
@@ -294,7 +481,7 @@ public final T readObject(String localName, ReadValueCallback
* the expected {@code startTagName}
* @throws XMLStreamException If the object cannot be read.
*/
- public final T readObject(String namespaceUri, String localName, ReadValueCallback converter)
+ public T readObject(String namespaceUri, String localName, ReadValueCallback converter)
throws XMLStreamException {
return readObject(new QName(namespaceUri, localName), converter);
}
@@ -331,7 +518,7 @@ private T readObject(QName startTagName, ReadValueCallback con
* {@link XmlToken#START_ELEMENT}.
* @throws XMLStreamException If skipping the element fails.
*/
- public final void skipElement() throws XMLStreamException {
+ public void skipElement() throws XMLStreamException {
XmlToken currentToken = currentToken();
if (currentToken != XmlToken.START_ELEMENT) {
return;
@@ -352,4 +539,23 @@ public final void skipElement() throws XMLStreamException {
}
}
}
+
+ private static XmlToken convertEventToToken(int event) {
+ switch (event) {
+ case 1:
+ return XmlToken.START_ELEMENT;
+
+ case 2:
+ return XmlToken.END_ELEMENT;
+
+ case 7:
+ return XmlToken.START_DOCUMENT;
+
+ case 8:
+ return XmlToken.END_DOCUMENT;
+
+ default:
+ throw new IllegalStateException("Unknown/unsupported XMLStreamConstants: " + event);
+ }
+ }
}
diff --git a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlSerializable.java b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlSerializable.java
index 6e80d8e8b51a..aeeb4c48ee17 100644
--- a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlSerializable.java
+++ b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlSerializable.java
@@ -9,10 +9,19 @@
* Indicates that the implementing class can be serialized to and deserialized from XML.
*
* Since deserialization needs to work without an instance of the class, implementing this interface it's assumed the
- * class has a static method {@code fromXml(XmlReader)} that deserializes an instance of that class. The contract for
- * reading XML... TODO (alzimmer): finish this javadoc
+ * class has static methods {@link #fromXml(XmlReader)} and {@link #fromXml(XmlReader, String)} that deserializes an
+ * instance of that class. The contract for reading XML from {@link XmlReader} is that the initial state of the reader
+ * on call will either be a null {@link XmlToken} or be {@link XmlToken#START_ELEMENT} for the object. So, for objects
+ * calling out to other {@link XmlSerializable} objects for deserialization, they'll pass the reader pointing to the
+ * token after the {@link XmlToken#START_ELEMENT}. This way objects reading XML will be self-encapsulated for reading
+ * properly formatted XML. And, if an error occurs during deserialization an {@link IllegalStateException} should be
+ * thrown.
*
* @param The type of the object that is XML serializable.
+ *
+ * @see com.azure.xml
+ * @see XmlReader
+ * @see XmlWriter
*/
public interface XmlSerializable> {
/**
@@ -24,7 +33,7 @@ public interface XmlSerializable> {
* writing XML will be self-encapsulated for writing properly formatted XML.
*
* @param xmlWriter The {@link XmlWriter} being written to.
- * @return The {@link XmlWriter} where the JSON was written for chaining.
+ * @return The {@link XmlWriter} where the XML was written for chaining.
* @throws XMLStreamException If the object fails to be written to the {@code xmlWriter}.
*/
XmlWriter toXml(XmlWriter xmlWriter) throws XMLStreamException;
@@ -40,7 +49,7 @@ public interface XmlSerializable> {
* @param xmlWriter The {@link XmlWriter} being written to.
* @param rootElementName Optional root element name to override the default defined by the model. Used to support
* cases where the model can serialize using different root element names.
- * @return The {@link XmlWriter} where the JSON was written for chaining.
+ * @return The {@link XmlWriter} where the XML was written for chaining.
* @throws XMLStreamException If the object fails to be written to the {@code xmlWriter}.
*/
XmlWriter toXml(XmlWriter xmlWriter, String rootElementName) throws XMLStreamException;
diff --git a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlWriter.java b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlWriter.java
index 345f8f1d591e..039d053e886e 100644
--- a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlWriter.java
+++ b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/XmlWriter.java
@@ -3,18 +3,80 @@
package com.azure.xml;
+import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
import java.util.Base64;
+import java.util.Objects;
+
+import static javax.xml.XMLConstants.DEFAULT_NS_PREFIX;
/**
* Writes an XML encoded value to a stream.
*/
@SuppressWarnings("resource")
-public abstract class XmlWriter implements AutoCloseable {
+public final class XmlWriter implements AutoCloseable {
+ private static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance();
+
+ private final XMLStreamWriter writer;
+
+ /**
+ * Creates an instance of {@link XmlWriter} that writes to the provided {@link OutputStream}.
+ *
+ * This uses the {@link XMLStreamWriter} implementation provided by the default
+ * {@link XMLOutputFactory#newInstance()}. If you need to provide a custom implementation of
+ * {@link XMLStreamWriter} use {@link #fromXmlStreamWriter(XMLStreamWriter)}.
+ *
+ * @param xml The {@link OutputStream} where content will be written.
+ * @return A new instance of {@link XmlWriter}.
+ * @throws NullPointerException If {@code xml} is null.
+ * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
+ */
+ public static XmlWriter toStream(OutputStream xml) throws XMLStreamException {
+ Objects.requireNonNull(xml, "'xml' cannot be null.");
+ return new XmlWriter(
+ XML_OUTPUT_FACTORY.createXMLStreamWriter(new OutputStreamWriter(xml, StandardCharsets.UTF_8)));
+ }
+
+ /**
+ * Creates an instance of {@link XmlWriter} that writes to the provided {@link Writer}.
+ *
+ * This uses the {@link XMLStreamWriter} implementation provided by the default
+ * {@link XMLOutputFactory#newInstance()}. If you need to provide a custom implementation of
+ * {@link XMLStreamWriter} use {@link #fromXmlStreamWriter(XMLStreamWriter)}.
+ *
+ * @param xml The {@link Writer} where content will be written.
+ * @return A new instance of {@link XmlWriter}.
+ * @throws NullPointerException If {@code xml} is null.
+ * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
+ */
+ public static XmlWriter toWriter(Writer xml) throws XMLStreamException {
+ Objects.requireNonNull(xml, "'xml' cannot be null.");
+ return new XmlWriter(XML_OUTPUT_FACTORY.createXMLStreamWriter(xml));
+ }
+
+ /**
+ * Creates an instance of {@link XmlWriter} that writes to the provided {@link XMLStreamWriter}.
+ *
+ * @param writer The {@link XMLStreamWriter} where content will be written.
+ * @return A new instance of {@link XmlWriter}.
+ * @throws NullPointerException If {@code writer} is null.
+ */
+ public static XmlWriter fromXmlStreamWriter(XMLStreamWriter writer) {
+ return new XmlWriter(writer);
+ }
+
/**
* Creates an instance of {@link XmlWriter}.
+ *
+ * @param writer The {@link XMLStreamWriter} where content will be written.
*/
- public XmlWriter() {
+ private XmlWriter(XMLStreamWriter writer) {
+ this.writer = Objects.requireNonNull(writer, "'writer' cannot be null.");
}
/**
@@ -27,7 +89,7 @@ public XmlWriter() {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML start document cannot be written.
*/
- public final XmlWriter writeStartDocument() throws XMLStreamException {
+ public XmlWriter writeStartDocument() throws XMLStreamException {
return writeStartDocument("1.0", "UTF-8");
}
@@ -42,7 +104,10 @@ public final XmlWriter writeStartDocument() throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML start document cannot be written.
*/
- public abstract XmlWriter writeStartDocument(String version, String encoding) throws XMLStreamException;
+ public XmlWriter writeStartDocument(String version, String encoding) throws XMLStreamException {
+ writer.writeStartDocument(encoding, version);
+ return this;
+ }
/**
* Begins an XML element start ({@code }).
@@ -92,7 +164,7 @@ public final XmlWriter writeStartElement(String localName) throws XMLStreamExcep
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element start cannot be written.
*/
- public final XmlWriter writeStartSelfClosingElement(String localName) throws XMLStreamException {
+ public XmlWriter writeStartSelfClosingElement(String localName) throws XMLStreamException {
return writeStartSelfClosingElement(null, localName);
}
@@ -112,8 +184,14 @@ public final XmlWriter writeStartSelfClosingElement(String localName) throws XML
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element start cannot be written.
*/
- public abstract XmlWriter writeStartSelfClosingElement(String namespaceUri, String localName)
- throws XMLStreamException;
+ public XmlWriter writeStartSelfClosingElement(String namespaceUri, String localName) throws XMLStreamException {
+ if (namespaceUri == null) {
+ writer.writeEmptyElement(localName);
+ } else {
+ writer.writeEmptyElement(namespaceUri, localName);
+ }
+ return this;
+ }
/**
* Ends the current XML element by writing the closing tag ({@code }).
@@ -124,7 +202,10 @@ public abstract XmlWriter writeStartSelfClosingElement(String namespaceUri, Stri
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element end cannot be written.
*/
- public abstract XmlWriter writeEndElement() throws XMLStreamException;
+ public XmlWriter writeEndElement() throws XMLStreamException {
+ writer.writeEndElement();
+ return this;
+ }
/**
* Writes a default XML namespace.
@@ -133,7 +214,15 @@ public abstract XmlWriter writeStartSelfClosingElement(String namespaceUri, Stri
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML namespace cannot be written.
*/
- public abstract XmlWriter writeNamespace(String namespaceUri) throws XMLStreamException;
+ public XmlWriter writeNamespace(String namespaceUri) throws XMLStreamException {
+ if (Objects.equals(writer.getNamespaceContext().getNamespaceURI(DEFAULT_NS_PREFIX), namespaceUri)) {
+ return this;
+ }
+
+ writer.setDefaultNamespace(namespaceUri);
+ writer.writeDefaultNamespace(namespaceUri);
+ return this;
+ }
/**
* Writes an XML namespace with a specified prefix.
@@ -146,7 +235,18 @@ public abstract XmlWriter writeStartSelfClosingElement(String namespaceUri, Stri
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML namespace cannot be written.
*/
- public abstract XmlWriter writeNamespace(String namespacePrefix, String namespaceUri) throws XMLStreamException;
+ public XmlWriter writeNamespace(String namespacePrefix, String namespaceUri) throws XMLStreamException {
+ if (namespacePrefix == null || "xmlns".equals(namespacePrefix)) {
+ return writeNamespace(namespacePrefix);
+ }
+
+ if (Objects.equals(writer.getNamespaceContext().getNamespaceURI(namespacePrefix), namespaceUri)) {
+ return this;
+ }
+
+ writer.writeNamespace(namespacePrefix, namespaceUri);
+ return this;
+ }
/**
* Writes a String attribute ({@code attribute="value"}).
@@ -156,7 +256,7 @@ public abstract XmlWriter writeStartSelfClosingElement(String namespaceUri, Stri
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeStringAttribute(String localName, String value) throws XMLStreamException {
+ public XmlWriter writeStringAttribute(String localName, String value) throws XMLStreamException {
return writeStringAttribute(null, localName, value);
}
@@ -169,8 +269,19 @@ public final XmlWriter writeStringAttribute(String localName, String value) thro
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public abstract XmlWriter writeStringAttribute(String namespaceUri, String localName, String value)
- throws XMLStreamException;
+ public XmlWriter writeStringAttribute(String namespaceUri, String localName, String value)
+ throws XMLStreamException {
+ if (value == null) {
+ return this;
+ }
+
+ if (namespaceUri == null) {
+ writer.writeAttribute(localName, value);
+ } else {
+ writer.writeAttribute(namespaceUri, localName, value);
+ }
+ return this;
+ }
/**
* Writes a binary attribute as a base64 string ({@code attribute="value"}).
@@ -182,7 +293,7 @@ public abstract XmlWriter writeStringAttribute(String namespaceUri, String local
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeBinaryAttribute(String localName, byte[] value) throws XMLStreamException {
+ public XmlWriter writeBinaryAttribute(String localName, byte[] value) throws XMLStreamException {
return writeBinaryAttribute(null, localName, value);
}
@@ -197,7 +308,7 @@ public final XmlWriter writeBinaryAttribute(String localName, byte[] value) thro
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeBinaryAttribute(String namespaceUri, String localName, byte[] value)
+ public XmlWriter writeBinaryAttribute(String namespaceUri, String localName, byte[] value)
throws XMLStreamException {
if (value == null) {
return this;
@@ -214,7 +325,7 @@ public final XmlWriter writeBinaryAttribute(String namespaceUri, String localNam
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeBooleanAttribute(String localName, boolean value) throws XMLStreamException {
+ public XmlWriter writeBooleanAttribute(String localName, boolean value) throws XMLStreamException {
return writeStringAttribute(localName, String.valueOf(value));
}
@@ -227,7 +338,7 @@ public final XmlWriter writeBooleanAttribute(String localName, boolean value) th
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeBooleanAttribute(String namespaceUri, String localName, boolean value)
+ public XmlWriter writeBooleanAttribute(String namespaceUri, String localName, boolean value)
throws XMLStreamException {
return writeStringAttribute(namespaceUri, localName, String.valueOf(value));
}
@@ -242,7 +353,7 @@ public final XmlWriter writeBooleanAttribute(String namespaceUri, String localNa
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeBooleanAttribute(String localName, Boolean value) throws XMLStreamException {
+ public XmlWriter writeBooleanAttribute(String localName, Boolean value) throws XMLStreamException {
return writeBooleanAttribute(null, localName, value);
}
@@ -257,7 +368,7 @@ public final XmlWriter writeBooleanAttribute(String localName, Boolean value) th
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeBooleanAttribute(String namespaceUri, String localName, Boolean value)
+ public XmlWriter writeBooleanAttribute(String namespaceUri, String localName, Boolean value)
throws XMLStreamException {
if (value == null) {
return this;
@@ -274,7 +385,7 @@ public final XmlWriter writeBooleanAttribute(String namespaceUri, String localNa
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeDoubleAttribute(String localName, double value) throws XMLStreamException {
+ public XmlWriter writeDoubleAttribute(String localName, double value) throws XMLStreamException {
return writeStringAttribute(localName, String.valueOf(value));
}
@@ -287,7 +398,7 @@ public final XmlWriter writeDoubleAttribute(String localName, double value) thro
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeDoubleAttribute(String namespaceUri, String localName, double value)
+ public XmlWriter writeDoubleAttribute(String namespaceUri, String localName, double value)
throws XMLStreamException {
return writeStringAttribute(namespaceUri, localName, String.valueOf(value));
}
@@ -300,7 +411,7 @@ public final XmlWriter writeDoubleAttribute(String namespaceUri, String localNam
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeFloatAttribute(String localName, float value) throws XMLStreamException {
+ public XmlWriter writeFloatAttribute(String localName, float value) throws XMLStreamException {
return writeStringAttribute(localName, String.valueOf(value));
}
@@ -313,8 +424,7 @@ public final XmlWriter writeFloatAttribute(String localName, float value) throws
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeFloatAttribute(String namespaceUri, String localName, float value)
- throws XMLStreamException {
+ public XmlWriter writeFloatAttribute(String namespaceUri, String localName, float value) throws XMLStreamException {
return writeStringAttribute(namespaceUri, localName, String.valueOf(value));
}
@@ -326,7 +436,7 @@ public final XmlWriter writeFloatAttribute(String namespaceUri, String localName
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeIntAttribute(String localName, int value) throws XMLStreamException {
+ public XmlWriter writeIntAttribute(String localName, int value) throws XMLStreamException {
return writeStringAttribute(localName, String.valueOf(value));
}
@@ -339,8 +449,7 @@ public final XmlWriter writeIntAttribute(String localName, int value) throws XML
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeIntAttribute(String namespaceUri, String localName, int value)
- throws XMLStreamException {
+ public XmlWriter writeIntAttribute(String namespaceUri, String localName, int value) throws XMLStreamException {
return writeStringAttribute(namespaceUri, localName, String.valueOf(value));
}
@@ -352,7 +461,7 @@ public final XmlWriter writeIntAttribute(String namespaceUri, String localName,
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeLongAttribute(String localName, long value) throws XMLStreamException {
+ public XmlWriter writeLongAttribute(String localName, long value) throws XMLStreamException {
return writeStringAttribute(localName, String.valueOf(value));
}
@@ -365,8 +474,7 @@ public final XmlWriter writeLongAttribute(String localName, long value) throws X
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeLongAttribute(String namespaceUri, String localName, long value)
- throws XMLStreamException {
+ public XmlWriter writeLongAttribute(String namespaceUri, String localName, long value) throws XMLStreamException {
return writeStringAttribute(namespaceUri, localName, String.valueOf(value));
}
@@ -378,7 +486,7 @@ public final XmlWriter writeLongAttribute(String namespaceUri, String localName,
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeNumberAttribute(String localName, Number value) throws XMLStreamException {
+ public XmlWriter writeNumberAttribute(String localName, Number value) throws XMLStreamException {
return writeNumberAttribute(null, localName, value);
}
@@ -391,7 +499,7 @@ public final XmlWriter writeNumberAttribute(String localName, Number value) thro
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML attribute cannot be written.
*/
- public final XmlWriter writeNumberAttribute(String namespaceUri, String localName, Number value)
+ public XmlWriter writeNumberAttribute(String namespaceUri, String localName, Number value)
throws XMLStreamException {
if (value == null) {
return this;
@@ -410,7 +518,7 @@ public final XmlWriter writeNumberAttribute(String namespaceUri, String localNam
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeBinaryElement(String localName, byte[] value) throws XMLStreamException {
+ public XmlWriter writeBinaryElement(String localName, byte[] value) throws XMLStreamException {
return writeBinaryElement(null, localName, value);
}
@@ -425,8 +533,7 @@ public final XmlWriter writeBinaryElement(String localName, byte[] value) throws
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeBinaryElement(String namespaceUri, String localName, byte[] value)
- throws XMLStreamException {
+ public XmlWriter writeBinaryElement(String namespaceUri, String localName, byte[] value) throws XMLStreamException {
if (value == null) {
return this;
}
@@ -442,7 +549,7 @@ public final XmlWriter writeBinaryElement(String namespaceUri, String localName,
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeBooleanElement(String localName, boolean value) throws XMLStreamException {
+ public XmlWriter writeBooleanElement(String localName, boolean value) throws XMLStreamException {
return writeBooleanElement(null, localName, value);
}
@@ -455,7 +562,7 @@ public final XmlWriter writeBooleanElement(String localName, boolean value) thro
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeBooleanElement(String namespaceUri, String localName, boolean value)
+ public XmlWriter writeBooleanElement(String namespaceUri, String localName, boolean value)
throws XMLStreamException {
return writeStartElement(namespaceUri, localName).writeBoolean(value).writeEndElement();
}
@@ -470,7 +577,7 @@ public final XmlWriter writeBooleanElement(String namespaceUri, String localName
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeBooleanElement(String localName, Boolean value) throws XMLStreamException {
+ public XmlWriter writeBooleanElement(String localName, Boolean value) throws XMLStreamException {
return writeBooleanElement(null, localName, value);
}
@@ -485,7 +592,7 @@ public final XmlWriter writeBooleanElement(String localName, Boolean value) thro
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeBooleanElement(String namespaceUri, String localName, Boolean value)
+ public XmlWriter writeBooleanElement(String namespaceUri, String localName, Boolean value)
throws XMLStreamException {
if (value == null) {
return this;
@@ -502,7 +609,7 @@ public final XmlWriter writeBooleanElement(String namespaceUri, String localName
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeDoubleElement(String localName, double value) throws XMLStreamException {
+ public XmlWriter writeDoubleElement(String localName, double value) throws XMLStreamException {
return writeDoubleElement(null, localName, value);
}
@@ -515,8 +622,7 @@ public final XmlWriter writeDoubleElement(String localName, double value) throws
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeDoubleElement(String namespaceUri, String localName, double value)
- throws XMLStreamException {
+ public XmlWriter writeDoubleElement(String namespaceUri, String localName, double value) throws XMLStreamException {
return writeStartElement(namespaceUri, localName).writeDouble(value).writeEndElement();
}
@@ -528,7 +634,7 @@ public final XmlWriter writeDoubleElement(String namespaceUri, String localName,
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeFloatElement(String localName, float value) throws XMLStreamException {
+ public XmlWriter writeFloatElement(String localName, float value) throws XMLStreamException {
return writeFloatElement(null, localName, value);
}
@@ -541,8 +647,7 @@ public final XmlWriter writeFloatElement(String localName, float value) throws X
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeFloatElement(String namespaceUri, String localName, float value)
- throws XMLStreamException {
+ public XmlWriter writeFloatElement(String namespaceUri, String localName, float value) throws XMLStreamException {
return writeStartElement(namespaceUri, localName).writeFloat(value).writeEndElement();
}
@@ -554,7 +659,7 @@ public final XmlWriter writeFloatElement(String namespaceUri, String localName,
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeIntElement(String localName, int value) throws XMLStreamException {
+ public XmlWriter writeIntElement(String localName, int value) throws XMLStreamException {
return writeIntElement(null, localName, value);
}
@@ -567,7 +672,7 @@ public final XmlWriter writeIntElement(String localName, int value) throws XMLSt
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeIntElement(String namespaceUri, String localName, int value) throws XMLStreamException {
+ public XmlWriter writeIntElement(String namespaceUri, String localName, int value) throws XMLStreamException {
return writeStartElement(namespaceUri, localName).writeInt(value).writeEndElement();
}
@@ -579,7 +684,7 @@ public final XmlWriter writeIntElement(String namespaceUri, String localName, in
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeLongElement(String localName, long value) throws XMLStreamException {
+ public XmlWriter writeLongElement(String localName, long value) throws XMLStreamException {
return writeLongElement(null, localName, value);
}
@@ -592,8 +697,7 @@ public final XmlWriter writeLongElement(String localName, long value) throws XML
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeLongElement(String namespaceUri, String localName, long value)
- throws XMLStreamException {
+ public XmlWriter writeLongElement(String namespaceUri, String localName, long value) throws XMLStreamException {
return writeStartElement(namespaceUri, localName).writeLong(value).writeEndElement();
}
@@ -607,7 +711,7 @@ public final XmlWriter writeLongElement(String namespaceUri, String localName, l
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeNumberElement(String localName, Number value) throws XMLStreamException {
+ public XmlWriter writeNumberElement(String localName, Number value) throws XMLStreamException {
return writeNumberElement(null, localName, value);
}
@@ -622,8 +726,7 @@ public final XmlWriter writeNumberElement(String localName, Number value) throws
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeNumberElement(String namespaceUri, String localName, Number value)
- throws XMLStreamException {
+ public XmlWriter writeNumberElement(String namespaceUri, String localName, Number value) throws XMLStreamException {
if (value == null) {
return this;
}
@@ -641,7 +744,7 @@ public final XmlWriter writeNumberElement(String namespaceUri, String localName,
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeStringElement(String localName, String value) throws XMLStreamException {
+ public XmlWriter writeStringElement(String localName, String value) throws XMLStreamException {
return writeStringElement(null, localName, value);
}
@@ -656,8 +759,7 @@ public final XmlWriter writeStringElement(String localName, String value) throws
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML element and value cannot be written.
*/
- public final XmlWriter writeStringElement(String namespaceUri, String localName, String value)
- throws XMLStreamException {
+ public XmlWriter writeStringElement(String namespaceUri, String localName, String value) throws XMLStreamException {
if (value == null) {
return this;
}
@@ -674,7 +776,7 @@ public final XmlWriter writeStringElement(String namespaceUri, String localName,
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML object cannot be written.
*/
- public final XmlWriter writeXml(XmlSerializable> value) throws XMLStreamException {
+ public XmlWriter writeXml(XmlSerializable> value) throws XMLStreamException {
return writeXml(value, null);
}
@@ -690,7 +792,7 @@ public final XmlWriter writeXml(XmlSerializable> value) throws XMLStreamExcept
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML object cannot be written.
*/
- public final XmlWriter writeXml(XmlSerializable> value, String rootElementName) throws XMLStreamException {
+ public XmlWriter writeXml(XmlSerializable> value, String rootElementName) throws XMLStreamException {
return value == null ? this : value.toXml(this, rootElementName);
}
@@ -703,7 +805,7 @@ public final XmlWriter writeXml(XmlSerializable> value, String rootElementName
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public final XmlWriter writeBinary(byte[] value) throws XMLStreamException {
+ public XmlWriter writeBinary(byte[] value) throws XMLStreamException {
return value == null ? this : writeString(convertBytesToString(value));
}
@@ -714,7 +816,7 @@ public final XmlWriter writeBinary(byte[] value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public final XmlWriter writeBoolean(boolean value) throws XMLStreamException {
+ public XmlWriter writeBoolean(boolean value) throws XMLStreamException {
return writeString(String.valueOf(value));
}
@@ -727,7 +829,7 @@ public final XmlWriter writeBoolean(boolean value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public final XmlWriter writeBoolean(Boolean value) throws XMLStreamException {
+ public XmlWriter writeBoolean(Boolean value) throws XMLStreamException {
return value == null ? this : writeString(String.valueOf(value));
}
@@ -738,7 +840,7 @@ public final XmlWriter writeBoolean(Boolean value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public final XmlWriter writeDouble(double value) throws XMLStreamException {
+ public XmlWriter writeDouble(double value) throws XMLStreamException {
return writeString(String.valueOf(value));
}
@@ -749,7 +851,7 @@ public final XmlWriter writeDouble(double value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public final XmlWriter writeFloat(float value) throws XMLStreamException {
+ public XmlWriter writeFloat(float value) throws XMLStreamException {
return writeString(String.valueOf(value));
}
@@ -760,7 +862,7 @@ public final XmlWriter writeFloat(float value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public final XmlWriter writeInt(int value) throws XMLStreamException {
+ public XmlWriter writeInt(int value) throws XMLStreamException {
return writeString(String.valueOf(value));
}
@@ -771,7 +873,7 @@ public final XmlWriter writeInt(int value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public final XmlWriter writeLong(long value) throws XMLStreamException {
+ public XmlWriter writeLong(long value) throws XMLStreamException {
return writeString(String.valueOf(value));
}
@@ -784,7 +886,7 @@ public final XmlWriter writeLong(long value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public final XmlWriter writeNumber(Number value) throws XMLStreamException {
+ public XmlWriter writeNumber(Number value) throws XMLStreamException {
return value == null ? this : writeString(String.valueOf(value));
}
@@ -799,7 +901,14 @@ public final XmlWriter writeNumber(Number value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML value cannot be written.
*/
- public abstract XmlWriter writeString(String value) throws XMLStreamException;
+ public XmlWriter writeString(String value) throws XMLStreamException {
+ if (value == null) {
+ return this;
+ }
+
+ writer.writeCharacters(value);
+ return this;
+ }
/**
* Writes a CData value directly into an XML element ({@code }).
@@ -813,7 +922,14 @@ public final XmlWriter writeNumber(Number value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the XML CData value cannot be written.
*/
- public abstract XmlWriter writeCDataString(String value) throws XMLStreamException;
+ public XmlWriter writeCDataString(String value) throws XMLStreamException {
+ if (value == null) {
+ return this;
+ }
+
+ writer.writeCData(value);
+ return this;
+ }
/**
* Flushes any un-flushed content that has been written to the {@link XmlWriter}.
@@ -821,7 +937,10 @@ public final XmlWriter writeNumber(Number value) throws XMLStreamException {
* @return The updated XmlWriter object.
* @throws XMLStreamException If the un-flushed XML content could not be flushed.
*/
- public abstract XmlWriter flush() throws XMLStreamException;
+ public XmlWriter flush() throws XMLStreamException {
+ writer.flush();
+ return this;
+ }
/**
* Closes the XML stream.
@@ -831,7 +950,10 @@ public final XmlWriter writeNumber(Number value) throws XMLStreamException {
* @throws XMLStreamException If the underlying content store fails to close.
*/
@Override
- public abstract void close() throws XMLStreamException;
+ public void close() throws XMLStreamException {
+ writer.flush();
+ writer.close();
+ }
private static String convertBytesToString(byte[] bytes) {
if (bytes == null) {
diff --git a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/DefaultXmlReader.java b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/DefaultXmlReader.java
deleted file mode 100644
index bdbff6e94aad..000000000000
--- a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/DefaultXmlReader.java
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.xml.implementation;
-
-import com.azure.xml.XmlReader;
-import com.azure.xml.XmlToken;
-import com.azure.xml.XmlWriter;
-
-import javax.xml.namespace.QName;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.Objects;
-
-/**
- * Default {@link XmlWriter} implementation based on {@link XMLStreamReader}.
- */
-public final class DefaultXmlReader extends XmlReader {
- private static final XMLInputFactory XML_INPUT_FACTORY;
-
- static {
- XML_INPUT_FACTORY = XMLInputFactory.newInstance();
- XML_INPUT_FACTORY.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
- XML_INPUT_FACTORY.setProperty(XMLInputFactory.SUPPORT_DTD, false);
- }
-
- private final XMLStreamReader reader;
-
- private XmlToken currentToken;
-
- /**
- * Creates an {@link XMLStreamReader}-based {@link XmlReader} that parses the passed {@code xml}.
- *
- * @param xml The XML to parse.
- * @return A new {@link XmlReader} instance.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader fromBytes(byte[] xml) throws XMLStreamException {
- Objects.requireNonNull(xml, "'xml' cannot be null.");
- return fromStream(new ByteArrayInputStream(xml));
- }
-
- /**
- * Creates an {@link XmlReader} that parses the passed {@code xml}.
- *
- * @param xml The XML to parse.
- * @return A new {@link XmlReader} instance.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader fromString(String xml) throws XMLStreamException {
- Objects.requireNonNull(xml, "'xml' cannot be null.");
- return fromReader(new StringReader(xml));
- }
-
- /**
- * Creates an {@link XmlReader} that parses the passed {@code xml}.
- *
- * @param xml The XML to parse.
- * @return A new {@link XmlReader} instance.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader fromStream(InputStream xml) throws XMLStreamException {
- Objects.requireNonNull(xml, "'xml' cannot be null.");
- return new DefaultXmlReader(XML_INPUT_FACTORY.createXMLStreamReader(xml));
- }
-
- /**
- * Creates an {@link XmlReader} that parses the passed {@code xml}.
- *
- * @param xml The XML to parse.
- * @return A new {@link XmlReader} instance.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlReader} cannot be instantiated.
- */
- public static XmlReader fromReader(Reader xml) throws XMLStreamException {
- Objects.requireNonNull(xml, "'xml' cannot be null.");
- return new DefaultXmlReader(XML_INPUT_FACTORY.createXMLStreamReader(xml));
- }
-
- private DefaultXmlReader(XMLStreamReader reader) {
- this.reader = reader;
- this.currentToken = convertEventToToken(reader.getEventType());
- }
-
- @Override
- public XmlToken currentToken() {
- return currentToken;
- }
-
- @Override
- public XmlToken nextElement() throws XMLStreamException {
- int next = reader.next();
- while (next != XMLStreamConstants.START_ELEMENT
- && next != XMLStreamConstants.END_ELEMENT
- && next != XMLStreamConstants.END_DOCUMENT) {
- next = reader.next();
- }
-
- currentToken = convertEventToToken(next);
- return currentToken;
- }
-
- @Override
- public QName getElementName() {
- return reader.getName();
- }
-
- @Override
- public String getStringElement() throws XMLStreamException {
- // The default getElementText implementation in the JDK uses an internal buffer as the API handles merging
- // multiple text states, characters, CDATA, space, and entity reference, into a single String. This
- // generally results in overhead as most cases will only have a single read performed but that read will
- // be buffered into the buffer and then returned as-is. So instead, a custom implementation will be used
- // where a small String buffer will be used to contain the intermediate reads and when the terminal state
- // is reached if only a single read was performed the String can be return, and if the unlikely multiple
- // read scenario is triggered those Strings can be concatenated.
- //
- // This logic continues to work even if the underlying XMLStreamReader implementation, such as the one
- // used in Jackson XML through Woodstox, handles this already.
-
- int readCount = 0;
- String firstRead = null;
- String[] buffer = null;
- int stringBufferSize = 0;
- int nextEvent = reader.next();
-
- // Continue reading until the next event is the end of the element or an exception state.
- while (nextEvent != XMLStreamConstants.END_ELEMENT) {
- if (nextEvent == XMLStreamConstants.CHARACTERS
- || nextEvent == XMLStreamConstants.CDATA
- || nextEvent == XMLStreamConstants.SPACE
- || nextEvent == XMLStreamConstants.ENTITY_REFERENCE) {
- readCount++;
- if (readCount == 1) {
- firstRead = reader.getText();
- stringBufferSize = firstRead.length();
- } else {
- if (readCount == 2) {
- buffer = new String[4];
- buffer[0] = firstRead;
- }
-
- if (readCount > buffer.length - 1) {
- String[] newBuffer = new String[buffer.length * 2];
- System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
- buffer = newBuffer;
- }
-
- String readText = reader.getText();
- buffer[readCount - 1] = readText;
- stringBufferSize += readText.length();
- }
- } else if (nextEvent != XMLStreamConstants.PROCESSING_INSTRUCTION
- && nextEvent != XMLStreamConstants.COMMENT) {
- // Processing instructions and comments are ignored but anything else is unexpected.
- throw new XMLStreamException("Unexpected event type while reading element value " + nextEvent);
- }
-
- nextEvent = reader.next();
- }
-
- if (readCount == 0) {
- return null;
- } else if (readCount == 1) {
- return firstRead;
- } else {
- StringBuilder finalText = new StringBuilder(stringBufferSize);
- for (int i = 0; i < readCount; i++) {
- finalText.append(buffer[i]);
- }
-
- return finalText.toString();
- }
- }
-
- @Override
- public String getStringAttribute(String namespaceUri, String localName) {
- String value = reader.getAttributeValue(namespaceUri, localName);
-
- // Treat empty string as null.
- return "".equals(value) ? null : value;
- }
-
- @Override
- public void close() throws XMLStreamException {
- reader.close();
- }
-
- private static XmlToken convertEventToToken(int event) {
- switch (event) {
- case 1:
- return XmlToken.START_ELEMENT;
-
- case 2:
- return XmlToken.END_ELEMENT;
-
- case 7:
- return XmlToken.START_DOCUMENT;
-
- case 8:
- return XmlToken.END_DOCUMENT;
-
- default:
- throw new IllegalStateException("Unknown/unsupported XMLStreamConstants: " + event);
- }
- }
-}
diff --git a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/DefaultXmlWriter.java b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/DefaultXmlWriter.java
deleted file mode 100644
index 449ab0a06a95..000000000000
--- a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/DefaultXmlWriter.java
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.xml.implementation;
-
-import com.azure.xml.XmlWriter;
-
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.StandardCharsets;
-import java.util.Objects;
-
-import static javax.xml.XMLConstants.DEFAULT_NS_PREFIX;
-
-/**
- * Default {@link XmlWriter} implementation based on {@link XMLStreamWriter}.
- */
-public final class DefaultXmlWriter extends XmlWriter {
- private static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance();
-
- private final XMLStreamWriter writer;
-
- /**
- * Creates an instance of {@link XmlWriter} that writes to the provided {@link OutputStream}.
- *
- * @param xml The {@link OutputStream} where content will be written.
- * @return A new instance of {@link XmlWriter}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
- */
- public static XmlWriter toStream(OutputStream xml) throws XMLStreamException {
- Objects.requireNonNull(xml, "'xml' cannot be null.");
- return new DefaultXmlWriter(
- XML_OUTPUT_FACTORY.createXMLStreamWriter(new OutputStreamWriter(xml, StandardCharsets.UTF_8)));
- }
-
- /**
- * Creates an instance of {@link XmlWriter} that writes to the provided {@link Writer}.
- *
- * @param xml The {@link Writer} where content will be written.
- * @return A new instance of {@link XmlWriter}.
- * @throws NullPointerException If {@code xml} is null.
- * @throws XMLStreamException If an {@link XmlWriter} cannot be instantiated.
- */
- public static XmlWriter toWriter(Writer xml) throws XMLStreamException {
- Objects.requireNonNull(xml, "'xml' cannot be null.");
- return new DefaultXmlWriter(XML_OUTPUT_FACTORY.createXMLStreamWriter(xml));
- }
-
- private DefaultXmlWriter(XMLStreamWriter writer) {
- this.writer = writer;
- }
-
- @Override
- public XmlWriter writeStartDocument(String version, String encoding) throws XMLStreamException {
- writer.writeStartDocument(encoding, version);
- return this;
- }
-
- @Override
- public XmlWriter writeStartElement(String namespaceUri, String localName) throws XMLStreamException {
- if (namespaceUri == null) {
- writer.writeStartElement(localName);
- } else {
- writer.writeStartElement(namespaceUri, localName);
- }
- return this;
- }
-
- @Override
- public XmlWriter writeStartSelfClosingElement(String namespaceUri, String localName) throws XMLStreamException {
- if (namespaceUri == null) {
- writer.writeEmptyElement(localName);
- } else {
- writer.writeEmptyElement(namespaceUri, localName);
- }
- return this;
- }
-
- @Override
- public XmlWriter writeNamespace(String namespaceUri) throws XMLStreamException {
- if (Objects.equals(writer.getNamespaceContext().getNamespaceURI(DEFAULT_NS_PREFIX), namespaceUri)) {
- return this;
- }
-
- writer.setDefaultNamespace(namespaceUri);
- writer.writeDefaultNamespace(namespaceUri);
- return this;
- }
-
- @Override
- public XmlWriter writeNamespace(String namespacePrefix, String namespaceUri) throws XMLStreamException {
- if (namespacePrefix == null || "xmlns".equals(namespacePrefix)) {
- return writeNamespace(namespacePrefix);
- }
-
- if (Objects.equals(writer.getNamespaceContext().getNamespaceURI(namespacePrefix), namespaceUri)) {
- return this;
- }
-
- writer.writeNamespace(namespacePrefix, namespaceUri);
- return this;
- }
-
- @Override
- public XmlWriter writeEndElement() throws XMLStreamException {
- writer.writeEndElement();
- return this;
- }
-
- @Override
- public XmlWriter writeStringAttribute(String namespaceUri, String localName, String value)
- throws XMLStreamException {
- if (value == null) {
- return this;
- }
-
- if (namespaceUri == null) {
- writer.writeAttribute(localName, value);
- } else {
- writer.writeAttribute(namespaceUri, localName, value);
- }
- return this;
- }
-
- @Override
- public XmlWriter writeString(String value) throws XMLStreamException {
- if (value == null) {
- return this;
- }
-
- writer.writeCharacters(value);
- return this;
- }
-
- @Override
- public XmlWriter writeCDataString(String value) throws XMLStreamException {
- if (value == null) {
- return this;
- }
-
- writer.writeCData(value);
- return this;
- }
-
- @Override
- public XmlWriter flush() throws XMLStreamException {
- writer.flush();
- return this;
- }
-
- @Override
- public void close() throws XMLStreamException {
- writer.flush();
- writer.close();
- }
-}
diff --git a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/package-info.java b/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/package-info.java
deleted file mode 100644
index a33eb394f5d2..000000000000
--- a/sdk/serialization/azure-xml/src/main/java/com/azure/xml/implementation/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-/**
- * Package containing implementation classes for XML parsing.
- */
-package com.azure.xml.implementation;
diff --git a/sdk/serialization/azure-xml/src/main/java/module-info.java b/sdk/serialization/azure-xml/src/main/java/module-info.java
index 1a38d62f075d..9336476b78c5 100644
--- a/sdk/serialization/azure-xml/src/main/java/module-info.java
+++ b/sdk/serialization/azure-xml/src/main/java/module-info.java
@@ -5,7 +5,4 @@
requires java.xml;
exports com.azure.xml;
- exports com.azure.xml.implementation;
-
- uses com.azure.xml.XmlProvider;
}
diff --git a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/DefaultXmlReaderContractTests.java b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/DefaultXmlReaderContractTests.java
index a0aaf5defc13..220bfb6832b3 100644
--- a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/DefaultXmlReaderContractTests.java
+++ b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/DefaultXmlReaderContractTests.java
@@ -4,16 +4,15 @@
package com.azure.xml;
import com.azure.xml.contract.XmlReaderContractTests;
-import com.azure.xml.implementation.DefaultXmlReader;
import javax.xml.stream.XMLStreamException;
/**
- * Tests {@link DefaultXmlReader} against the contract required by {@link XmlReader}.
+ * Tests {@link XmlReader} against the contract required by {@link XmlReader}.
*/
public final class DefaultXmlReaderContractTests extends XmlReaderContractTests {
@Override
protected XmlReader getXmlReader(String xml) throws XMLStreamException {
- return DefaultXmlReader.fromString(xml);
+ return XmlReader.fromString(xml);
}
}
diff --git a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/DefaultXmlWriterContractTests.java b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/DefaultXmlWriterContractTests.java
index 982cc2bea6ba..30ac391d4964 100644
--- a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/DefaultXmlWriterContractTests.java
+++ b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/DefaultXmlWriterContractTests.java
@@ -4,7 +4,6 @@
package com.azure.xml;
import com.azure.xml.contract.XmlWriterContractTests;
-import com.azure.xml.implementation.DefaultXmlWriter;
import org.junit.jupiter.api.BeforeEach;
import javax.xml.stream.XMLStreamException;
@@ -13,7 +12,7 @@
import java.nio.charset.StandardCharsets;
/**
- * Tests {@link DefaultXmlWriter} against the contract required by {@link XmlWriter}.
+ * Tests {@link XmlWriter} against the contract required by {@link XmlWriter}.
*/
public final class DefaultXmlWriterContractTests extends XmlWriterContractTests {
private ByteArrayOutputStream outputStream;
@@ -22,7 +21,7 @@ public final class DefaultXmlWriterContractTests extends XmlWriterContractTests
@BeforeEach
public void beforeEach() throws XMLStreamException {
this.outputStream = new ByteArrayOutputStream();
- this.writer = DefaultXmlWriter.toStream(outputStream);
+ this.writer = XmlWriter.toStream(outputStream);
}
@Override
diff --git a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/PlaygroundTests.java b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/PlaygroundTests.java
index f03daf979d57..70d1c5090331 100644
--- a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/PlaygroundTests.java
+++ b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/PlaygroundTests.java
@@ -3,8 +3,6 @@
package com.azure.xml;
-import com.azure.xml.implementation.DefaultXmlReader;
-import com.azure.xml.implementation.DefaultXmlWriter;
import org.junit.jupiter.api.Test;
import javax.xml.stream.XMLStreamException;
@@ -48,7 +46,7 @@ public void toXmlSimple() throws XMLStreamException, UnsupportedEncodingExceptio
SignedIdentifiersWrapper wrapper = new SignedIdentifiersWrapper(Collections.singletonList(signedIdentifier));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- try (XmlWriter xmlWriter = DefaultXmlWriter.toStream(byteArrayOutputStream)) {
+ try (XmlWriter xmlWriter = XmlWriter.toStream(byteArrayOutputStream)) {
xmlWriter.writeStartDocument();
wrapper.toXml(xmlWriter);
}
@@ -68,7 +66,7 @@ public void fromXmlSimple() throws XMLStreamException {
SignedIdentifiersWrapper wrapper = new SignedIdentifiersWrapper(Collections.singletonList(signedIdentifier));
- try (XmlReader xmlReader = DefaultXmlReader.fromString(SIMPLE_XML)) {
+ try (XmlReader xmlReader = XmlReader.fromString(SIMPLE_XML)) {
SignedIdentifiersWrapper actualWrapper = SignedIdentifiersWrapper.fromXml(xmlReader);
assertNotNull(actualWrapper);
@@ -119,7 +117,7 @@ public void toXmlComplex() throws XMLStreamException, UnsupportedEncodingExcepti
.setContent(namespacePropertiesEntryContent);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- try (XmlWriter xmlWriter = DefaultXmlWriter.toStream(byteArrayOutputStream)) {
+ try (XmlWriter xmlWriter = XmlWriter.toStream(byteArrayOutputStream)) {
xmlWriter.writeStartDocument();
namespacePropertiesEntry.toXml(xmlWriter);
}
@@ -156,7 +154,7 @@ public void fromXmlComplex() throws XMLStreamException {
.setLink(responseLink)
.setContent(namespacePropertiesEntryContent);
- try (XmlReader xmlReader = DefaultXmlReader.fromString(COMPLEX_XML)) {
+ try (XmlReader xmlReader = XmlReader.fromString(COMPLEX_XML)) {
NamespacePropertiesEntry actualEntry = NamespacePropertiesEntry.fromXml(xmlReader);
assertNotNull(actualEntry);
diff --git a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/contract/XmlReaderContractTests.java b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/contract/XmlReaderContractTests.java
index 84bc4b4c7beb..7ada36c3a20e 100644
--- a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/contract/XmlReaderContractTests.java
+++ b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/contract/XmlReaderContractTests.java
@@ -126,9 +126,9 @@ private static Stream binaryElementOperationsSupplier() {
@ParameterizedTest
@MethodSource("basicAttributeOperationsSupplier")
- public void basicAttributeOperations(String json, T expectedValue, ReadValueCallback function)
+ public void basicAttributeOperations(String xml, T expectedValue, ReadValueCallback function)
throws XMLStreamException {
- XmlReader reader = getXmlReader(json);
+ XmlReader reader = getXmlReader(xml);
reader.nextElement(); // Initialize the XmlReader for reading.
T actualValue = assertDoesNotThrow(() -> function.read(reader));
diff --git a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/storage/DateTimeRfc1123.java b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/storage/DateTimeRfc1123.java
index 7c410f8935ba..975b8b29ea6f 100644
--- a/sdk/serialization/azure-xml/src/test/java/com/azure/xml/storage/DateTimeRfc1123.java
+++ b/sdk/serialization/azure-xml/src/test/java/com/azure/xml/storage/DateTimeRfc1123.java
@@ -44,7 +44,7 @@ public OffsetDateTime getDateTime() {
}
/**
- * JSON creator for DateTimeRfc1123.
+ * XML creator for DateTimeRfc1123.
*