You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2014/05/18 07:06:38 UTC

[10/38] git commit: [OLINGO-196] Added XML implementation

[OLINGO-196] Added XML implementation


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/9b1ba14b
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/9b1ba14b
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/9b1ba14b

Branch: refs/heads/Olingo-129_PocJpaDataStore
Commit: 9b1ba14ba5a12a9237904729b884836f77527128
Parents: 69e73b5
Author: Michael Bolz <mi...@apache.org>
Authored: Tue Mar 25 16:12:53 2014 +0100
Committer: Michael Bolz <mi...@apache.org>
Committed: Wed Mar 26 06:34:49 2014 +0100

----------------------------------------------------------------------
 .../olingo/odata2/core/commons/XmlHelper.java   |   4 +
 .../ep/consumer/XmlErrorDocumentConsumer.java   | 122 +++++++++-
 .../odata2/core/ep/ProviderFacadeImplTest.java  |  18 ++
 .../consumer/XmlErrorDocumentConsumerTest.java  | 228 +++++++++++++++++++
 4 files changed, 371 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9b1ba14b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/XmlHelper.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/XmlHelper.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/XmlHelper.java
index f4bf49b..3efa87b 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/XmlHelper.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/XmlHelper.java
@@ -32,6 +32,10 @@ public class XmlHelper {
   private static final String DEFAULT_CHARSET = "UTF-8";
 
   public static XMLStreamReader createStreamReader(final Object content) throws EntityProviderException {
+    if (content == null) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+              .addContent("Got not allowed NULL parameter for creation of XMLStreamReader."));
+    }
     XMLStreamReader streamReader;
     try {
       XMLInputFactory factory = XMLInputFactory.newInstance();

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9b1ba14b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
index 21f3f8c..d21cec4 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
@@ -19,14 +19,35 @@
 package org.apache.olingo.odata2.core.ep.consumer;
 
 import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
 
+import org.apache.olingo.odata2.api.edm.Edm;
 import org.apache.olingo.odata2.api.ep.EntityProviderException;
 import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.XmlHelper;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
 
 /**
  * Consuming (read / deserialization) for OData error document in XML format.
  */
 public class XmlErrorDocumentConsumer {
+  /** Map containing language code (language - country) to Locale mapping
+   * based on Locale.getAvailableLocales()
+   * */
+  private final static Map<String, Locale> AVAILABLE_LOCALES = new HashMap<String, Locale>();
+  static {
+    Locale[] locales = Locale.getAvailableLocales();
+    for (Locale l : locales) {
+      AVAILABLE_LOCALES.put(l.getLanguage() + "-" + l.getCountry(), l);
+    }
+  }
 
   /**
    * Deserialize / read OData error document in ODataErrorContext.
@@ -36,6 +57,105 @@ public class XmlErrorDocumentConsumer {
    * @throws EntityProviderException if an exception during read / deserialization occurs.
    */
   public ODataErrorContext readError(final InputStream errorDocument) throws EntityProviderException {
-    throw new RuntimeException("Not yet implementedØ");
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = XmlHelper.createStreamReader(errorDocument);
+      return parserError(reader);
+    } catch (XMLStreamException e) {
+      cachedException = new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(
+                      e.getMessage()), e);
+      throw cachedException;
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(
+                    EntityProviderException.EXCEPTION_OCCURRED.addContent(
+                            e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  private ODataErrorContext parserError(XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    // read xml tag
+    reader.require(XMLStreamConstants.START_DOCUMENT, null, null);
+    reader.nextTag();
+
+    // read error tag
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_ERROR);
+
+    // read error data
+    boolean codeFound = false;
+    boolean messageFound = false;
+    ODataErrorContext errorContext = new ODataErrorContext();
+    while(notFinished(reader)) {
+      reader.nextTag();
+      if(reader.isStartElement()) {
+        String name = reader.getLocalName();
+        if(FormatXml.M_CODE.equals(name)) {
+          codeFound = true;
+          handleCode(reader, errorContext);
+        } else if(FormatXml.M_MESSAGE.equals(name)) {
+          messageFound = true;
+          handleMessage(reader, errorContext);
+        } else if(FormatXml.M_INNER_ERROR.equals(name)) {
+          handleInnerError(reader, errorContext);
+        } else {
+          throw new EntityProviderException(
+                  EntityProviderException.INVALID_CONTENT.addContent(name, FormatXml.M_ERROR));
+        }
+      }
+    }
+    validate(codeFound, messageFound);
+
+    errorContext.setContentType(ContentType.APPLICATION_XML.toContentTypeString());
+    return errorContext;
+  }
+
+  private void validate(boolean codeFound, boolean messageFound) throws EntityProviderException {
+    if (!codeFound) {
+      throw new EntityProviderException(
+              EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'code' property not found.'"));
+    } else if (!messageFound) {
+      throw new EntityProviderException(
+              EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'message' property not found.'"));
+    }
+  }
+
+  private boolean notFinished(XMLStreamReader reader) throws XMLStreamException {
+    boolean finished = reader.isEndElement() && FormatXml.M_ERROR.equals(reader.getLocalName());
+    return !finished && reader.hasNext();
+  }
+
+  private void handleInnerError(XMLStreamReader reader, ODataErrorContext errorContext) throws XMLStreamException {
+    String innerError = reader.getElementText();
+    errorContext.setInnerError(innerError);
+  }
+
+  private void handleMessage(XMLStreamReader reader, ODataErrorContext errorContext) throws XMLStreamException {
+    String lang = reader.getAttributeValue(Edm.NAMESPACE_XML_1998, FormatXml.XML_LANG);
+    errorContext.setLocale(getLocale(lang));
+    String message = reader.getElementText();
+    errorContext.setMessage(message);
+  }
+
+  private void handleCode(XMLStreamReader reader, ODataErrorContext errorContext) throws XMLStreamException {
+    String code = reader.getElementText();
+    errorContext.setErrorCode(code);
+  }
+
+  private Locale getLocale(final String langValue) {
+    return AVAILABLE_LOCALES.get(langValue);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9b1ba14b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java
index fdc8525..58577aa 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java
@@ -249,6 +249,24 @@ public class ProviderFacadeImplTest extends AbstractConsumerTest {
   }
 
   @Test
+  public void readErrorDocumentXml() throws EntityProviderException {
+    ProviderFacadeImpl providerFacade = new ProviderFacadeImpl();
+    String errorDoc =
+            "<?xml version='1.0' encoding='UTF-8'?>\n" +
+            "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+            "\t<code>ErrorCode</code>\n" +
+            "\t<message xml:lang=\"en-US\">Message</message>\n" +
+            "</error>";
+    ODataErrorContext errorContext = providerFacade.readErrorDocument(StringHelper.encapsulate(errorDoc),
+            ContentType.APPLICATION_XML.toContentTypeString());
+    //
+    assertEquals("Wrong content type", "application/xml", errorContext.getContentType());
+    assertEquals("Wrong message", "Message", errorContext.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", errorContext.getErrorCode());
+    assertEquals("Wrong locale for lang", Locale.US, errorContext.getLocale());
+  }
+
+  @Test
   public void writeFeed() throws Exception {
     final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
     List<Map<String, Object>> propertiesList = new ArrayList<Map<String, Object>>();

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9b1ba14b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java
new file mode 100644
index 0000000..4106bcd
--- /dev/null
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.olingo.odata2.core.ep.consumer;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.junit.Test;
+
+import java.io.InputStream;
+import java.util.Locale;
+
+import static org.junit.Assert.*;
+
+/**
+ *  
+ */
+public class XmlErrorDocumentConsumerTest extends AbstractConsumerTest {
+
+  private static final String XML_ERROR_DOCUMENT_SIMPLE =
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:lang=\"en-US\">Message</message>\n" +
+                  "</error>";
+  private static final String XML_ERROR_DOCUMENT_NULL_LOCALE =
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:lang=\"\">Message</message>\n" +
+                  "</error>";
+  private static final String XML_ERROR_DOCUMENT_INNER_ERROR =
+  "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "<innererror>Some InnerError</innererror>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_INVALID_XML =
+  "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</CODE>\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "</error>";
+  /* error document with name 'locale' instead of 'lang' for message object */
+  private static final String XML_ERROR_DOCUMENT_UNKNOWN_CONTENT =
+  "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:locale=\"en-US\">Message</message>\n" +
+          "\t<privateMessage>Secret</privateMessage>\n" +
+          "</error>";
+  /* error document without value for message object */
+  private static final String XML_ERROR_DOCUMENT_EMPTY_MESSAGE =
+  "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"en-US\" />\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_MISSING_MESSAGE =
+  "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_MISSING_CODE =
+  "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "</error>";
+  private static final String XML_ERROR_DOCUMENT_MISSING_ERROR =
+  "<?xml version='1.0' encoding='UTF-8'?>\n" +
+          "<errorForMe xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">\n" +
+          "\t<code>ErrorCode</code>\n" +
+          "\t<message xml:lang=\"en-US\">Message</message>\n" +
+          "</errorForMe>";
+  private XmlErrorDocumentConsumer xedc = new XmlErrorDocumentConsumer();
+
+  @Test
+  public void simpleErrorDocument() throws Exception {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_SIMPLE);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong locale for lang", Locale.US, error.getLocale());
+  }
+
+  @Test
+  public void emptyMessage() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_EMPTY_MESSAGE);
+
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong locale for lang", Locale.US, error.getLocale());
+  }
+
+  @Test
+  public void localeNull() throws Exception {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_NULL_LOCALE);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertNull("Expected NULL for locale", error.getLocale());
+  }
+
+
+  @Test
+  public void innerError() throws Exception {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_INNER_ERROR);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", "Some InnerError", error.getInnerError());
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidJson() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_INVALID_XML);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidEmptyDocument() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate("");
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
+              EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void nullParameter() throws EntityProviderException {
+    try {
+      xedc.readError(null);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.ILLEGAL_ARGUMENT, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentUnknown() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_UNKNOWN_CONTENT);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.INVALID_CONTENT, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingError() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_MISSING_ERROR);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
+              EntityProviderException.INVALID_STATE, e.getMessageReference());
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingCode() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_MISSING_CODE);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
+              EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+      assertTrue(e.getMessage().contains("code"));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void invalidErrorDocumentMissingMessage() throws EntityProviderException {
+    InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_MISSING_MESSAGE);
+    try {
+      xedc.readError(in);
+      fail("Expected exception was not thrown");
+    } catch (EntityProviderException e) {
+      assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
+              EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+      assertTrue(e.getMessage().contains("message"));
+      throw e;
+    }
+  }
+}