Repository: olingo-odata4 Updated Branches: refs/heads/master 1a739d46b -> eea324d5a
[OLINGO-1249]OData Client API issue: Have a means to validate if a document isv4Metadata or isServiceDoc Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/eea324d5 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/eea324d5 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/eea324d5 Branch: refs/heads/master Commit: eea324d5a67ac346695937dd49e4a9c775cfb501 Parents: 1a739d4 Author: ramya vasanth <[email protected]> Authored: Tue Mar 20 13:54:47 2018 +0530 Committer: ramya vasanth <[email protected]> Committed: Tue Mar 20 13:54:47 2018 +0530 ---------------------------------------------------------------------- .../olingo/client/api/edm/xml/XMLMetadata.java | 117 +++--- .../serialization/ODataMetadataValidation.java | 12 + .../client/core/edm/ClientCsdlXMLMetadata.java | 166 ++++---- .../metadatavalidator/CsdlTypeValidator.java | 47 +++ .../ClientODataDeserializerImpl.java | 393 +++++++++++-------- .../ODataMetadataValidationImpl.java | 10 + .../client/core/MetadataValidationTest.java | 170 ++++++++ 7 files changed, 624 insertions(+), 291 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eea324d5/lib/client-api/src/main/java/org/apache/olingo/client/api/edm/xml/XMLMetadata.java ---------------------------------------------------------------------- diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/edm/xml/XMLMetadata.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/edm/xml/XMLMetadata.java index 74191cf..26013e5 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/edm/xml/XMLMetadata.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/edm/xml/XMLMetadata.java @@ -1,57 +1,60 @@ -/* - * 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.client.api.edm.xml; - -import java.util.List; -import java.util.Map; - -import org.apache.olingo.commons.api.edm.provider.CsdlSchema; - -/** - * Entry point for access information about EDM metadata. - */ -public interface XMLMetadata { - - /** - * Returns the Schema at the specified position in the EdM metadata document. - * - * @param index index of the Schema to return - * @return the Schema at the specified position in the EdM metadata document - */ - CsdlSchema getSchema(final int index); - - /** - * Returns the Schema with the specified key (namespace or alias) in the EdM metadata document. - * - * @param key namespace or alias - * @return the Schema with the specified key in the EdM metadata document - */ - CsdlSchema getSchema(final String key); - - /** - * Returns all Schema objects defined in the EdM metadata document. - * - * @return all Schema objects defined in the EdM metadata document - */ - List<CsdlSchema> getSchemas(); - - Map<String, CsdlSchema> getSchemaByNsOrAlias(); - - List<Reference> getReferences(); -} +/* + * 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.client.api.edm.xml; + +import java.util.List; +import java.util.Map; + +import org.apache.olingo.commons.api.edm.provider.CsdlSchema; + +/** + * Entry point for access information about EDM metadata. + */ +public interface XMLMetadata { + + /** + * Returns the Schema at the specified position in the EdM metadata document. + * + * @param index index of the Schema to return + * @return the Schema at the specified position in the EdM metadata document + */ + CsdlSchema getSchema(final int index); + + /** + * Returns the Schema with the specified key (namespace or alias) in the EdM metadata document. + * + * @param key namespace or alias + * @return the Schema with the specified key in the EdM metadata document + */ + CsdlSchema getSchema(final String key); + + /** + * Returns all Schema objects defined in the EdM metadata document. + * + * @return all Schema objects defined in the EdM metadata document + */ + List<CsdlSchema> getSchemas(); + + Map<String, CsdlSchema> getSchemaByNsOrAlias(); + + List<Reference> getReferences(); + + List<List<String>> getSchemaNamespaces(); + +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eea324d5/lib/client-api/src/main/java/org/apache/olingo/client/api/serialization/ODataMetadataValidation.java ---------------------------------------------------------------------- diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/serialization/ODataMetadataValidation.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/serialization/ODataMetadataValidation.java index f1bf5ef..86533f3 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/serialization/ODataMetadataValidation.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/serialization/ODataMetadataValidation.java @@ -34,4 +34,16 @@ public interface ODataMetadataValidation { * @param xmlMetadata */ void validateMetadata(XMLMetadata xmlMetadata); + + /** + * This method checks if if its a V4 metadata based on the XMLMetadata provided + * @param xmlMetadata + */ + boolean isV4Metadata(XMLMetadata xmlMetadata)throws Exception; + + /** + * This method checks if if its a service document based on the XMLMetadata provided + * @param xmlMetadata + */ + boolean isServiceDocument(XMLMetadata xmlMetadata); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eea324d5/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/ClientCsdlXMLMetadata.java ---------------------------------------------------------------------- diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/ClientCsdlXMLMetadata.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/ClientCsdlXMLMetadata.java index ac4f3e1..1507778 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/ClientCsdlXMLMetadata.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/ClientCsdlXMLMetadata.java @@ -1,76 +1,90 @@ -/* - * 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.client.core.edm; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; -import org.apache.olingo.client.api.edm.xml.Edmx; -import org.apache.olingo.client.api.edm.xml.Reference; -import org.apache.olingo.client.api.edm.xml.XMLMetadata; -import org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmItem; -import org.apache.olingo.commons.api.edm.provider.CsdlSchema; - -/** - * Entry point for access information about EDM metadata. - */ -public class ClientCsdlXMLMetadata extends CsdlAbstractEdmItem implements Serializable, XMLMetadata { - - private static final long serialVersionUID = 6025723060298454901L; - protected final Edmx edmx; - - public ClientCsdlXMLMetadata(final Edmx edmx) { - this.edmx = edmx; - } - - @Override - public List<CsdlSchema> getSchemas() { - return this.edmx.getDataServices().getSchemas(); - } - - @Override - public CsdlSchema getSchema(final int index) { - return getSchemas().get(index); - } - - @Override - public CsdlSchema getSchema(final String key) { - return getSchemaByNsOrAlias().get(key); - } - - @Override - public Map<String, CsdlSchema> getSchemaByNsOrAlias() { - final Map<String, CsdlSchema> schemaByNsOrAlias = new HashMap<String, CsdlSchema>(); - for (CsdlSchema schema : getSchemas()) { - schemaByNsOrAlias.put(schema.getNamespace(), schema); - if (StringUtils.isNotBlank(schema.getAlias())) { - schemaByNsOrAlias.put(schema.getAlias(), schema); - } - } - return schemaByNsOrAlias; - } - - @Override - public List<Reference> getReferences() { - return this.edmx.getReferences(); - } -} +/* + * 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.client.core.edm; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.apache.olingo.client.api.edm.xml.Edmx; +import org.apache.olingo.client.api.edm.xml.Reference; +import org.apache.olingo.client.api.edm.xml.XMLMetadata; +import org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmItem; +import org.apache.olingo.commons.api.edm.provider.CsdlSchema; + +/** + * Entry point for access information about EDM metadata. + */ +public class ClientCsdlXMLMetadata extends CsdlAbstractEdmItem implements Serializable, XMLMetadata { + + private static final long serialVersionUID = 6025723060298454901L; + protected final Edmx edmx; + private List<List<String>> schemaNameSpaces = null; + + public ClientCsdlXMLMetadata(final Edmx edmx) { + this.edmx = edmx; + } + public ClientCsdlXMLMetadata(final Edmx edmx,final List<List<String>> schemaNameSpaces) { + this.edmx = edmx; + this.schemaNameSpaces = schemaNameSpaces; + } + + + + @Override + public List<List<String>> getSchemaNamespaces() { + return schemaNameSpaces; + } + + + + @Override + public List<CsdlSchema> getSchemas() { + return this.edmx.getDataServices().getSchemas(); + } + + @Override + public CsdlSchema getSchema(final int index) { + return getSchemas().get(index); + } + + @Override + public CsdlSchema getSchema(final String key) { + return getSchemaByNsOrAlias().get(key); + } + + @Override + public Map<String, CsdlSchema> getSchemaByNsOrAlias() { + final Map<String, CsdlSchema> schemaByNsOrAlias = new HashMap<String, CsdlSchema>(); + for (CsdlSchema schema : getSchemas()) { + schemaByNsOrAlias.put(schema.getNamespace(), schema); + if (StringUtils.isNotBlank(schema.getAlias())) { + schemaByNsOrAlias.put(schema.getAlias(), schema); + } + } + return schemaByNsOrAlias; + } + + @Override + public List<Reference> getReferences() { + return this.edmx.getReferences(); + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eea324d5/lib/client-core/src/main/java/org/apache/olingo/client/core/metadatavalidator/CsdlTypeValidator.java ---------------------------------------------------------------------- diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/metadatavalidator/CsdlTypeValidator.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/metadatavalidator/CsdlTypeValidator.java index fbb28d0..4eef836 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/metadatavalidator/CsdlTypeValidator.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/metadatavalidator/CsdlTypeValidator.java @@ -19,10 +19,13 @@ package org.apache.olingo.client.core.metadatavalidator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.Map.Entry; +import org.apache.olingo.client.api.edm.xml.XMLMetadata; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.edm.provider.CsdlAction; import org.apache.olingo.commons.api.edm.provider.CsdlActionImport; @@ -34,6 +37,7 @@ import org.apache.olingo.commons.api.edm.provider.CsdlFunction; import org.apache.olingo.commons.api.edm.provider.CsdlFunctionImport; import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty; import org.apache.olingo.commons.api.edm.provider.CsdlNavigationPropertyBinding; +import org.apache.olingo.commons.api.edm.provider.CsdlSchema; import org.apache.olingo.commons.api.edm.provider.CsdlStructuralType; public class CsdlTypeValidator { @@ -49,7 +53,12 @@ public class CsdlTypeValidator { new HashMap<FullQualifiedName, CsdlAction>(); private Map<FullQualifiedName, CsdlFunction> csdlFunctionsMap = new HashMap<FullQualifiedName, CsdlFunction>(); + private static final String V4_SCHEMA_XMLNS = + "http://docs.oasis-open.org/odata/ns/edm"; + public CsdlTypeValidator(){ + + } /** * * @param aliasNamespaceMap @@ -492,4 +501,42 @@ public class CsdlTypeValidator { } return fqName; } + /** + * This checks if XmlMetadata is V4 OData version. + * @param xmlMetadata + * @return boolean + * @throws Exception + */ + public boolean isV4MetaData(XMLMetadata xmlMetadata) throws Exception { + boolean isV4doc = true; + List<List<String>>schemaNameSpaces = xmlMetadata.getSchemaNamespaces(); + if (schemaNameSpaces == null || schemaNameSpaces.isEmpty()) { + throw new Exception("Cannot determine if v4 metadata," + + "No schemanamespaces found in XMLMetadata"); + } + for(List<String> nameSpaces:schemaNameSpaces){ + if(!nameSpaces.contains(V4_SCHEMA_XMLNS)){ + isV4doc = false; + } + } + return isV4doc; +} + /** + * This checks if XMLMetadata is a service document. + * @param xmlMetadata + * @return boolean + */ + public boolean isServiceDocument(XMLMetadata xmlMetadata){ + boolean isServDoc = false; + List<CsdlSchema> schemas = xmlMetadata.getSchemas(); + for (CsdlSchema schema : schemas) { + // for metadata to be a service document it should have an entity + // container + if (schema.getEntityContainer() != null) { + isServDoc = true; + break; + } + } + return isServDoc; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eea324d5/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ClientODataDeserializerImpl.java ---------------------------------------------------------------------- diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ClientODataDeserializerImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ClientODataDeserializerImpl.java index fcb2ca0..9d02bab 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ClientODataDeserializerImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ClientODataDeserializerImpl.java @@ -1,158 +1,235 @@ -/* - * 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.client.core.serialization; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.stream.XMLStreamException; - -import org.apache.olingo.client.api.data.ResWrap; -import org.apache.olingo.client.api.data.ServiceDocument; -import org.apache.olingo.client.api.edm.xml.XMLMetadata; -import org.apache.olingo.client.api.serialization.ClientODataDeserializer; -import org.apache.olingo.client.api.serialization.ODataDeserializer; -import org.apache.olingo.client.api.serialization.ODataDeserializerException; -import org.apache.olingo.client.core.data.JSONServiceDocumentDeserializer; -import org.apache.olingo.client.core.data.XMLServiceDocumentDeserializer; -import org.apache.olingo.client.core.edm.ClientCsdlXMLMetadata; -import org.apache.olingo.client.core.edm.xml.ClientCsdlEdmx; -import org.apache.olingo.commons.api.data.Delta; -import org.apache.olingo.commons.api.data.Entity; -import org.apache.olingo.commons.api.data.EntityCollection; -import org.apache.olingo.commons.api.data.Property; -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; -import org.apache.olingo.commons.api.edm.provider.CsdlSchema; -import org.apache.olingo.commons.api.ex.ODataError; -import org.apache.olingo.commons.api.format.ContentType; - -import com.fasterxml.aalto.stax.InputFactoryImpl; -import com.fasterxml.aalto.stax.OutputFactoryImpl; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.InjectableValues; -import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; -import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; -import com.fasterxml.jackson.dataformat.xml.XmlFactory; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; - -public class ClientODataDeserializerImpl implements ClientODataDeserializer { - - private final ODataDeserializer deserializer; - private final ContentType contentType; - - public ClientODataDeserializerImpl(final boolean serverMode, final ContentType contentType) { - this.contentType = contentType; - if (contentType.isCompatible(ContentType.APPLICATION_ATOM_SVC) - || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML) - || contentType.isCompatible(ContentType.APPLICATION_XML)) { - deserializer = new AtomDeserializer(); - } else { - deserializer = new JsonDeserializer(serverMode); - } - } - - @Override - public ResWrap<EntityCollection> toEntitySet(final InputStream input) throws ODataDeserializerException { - return deserializer.toEntitySet(input); - } - - @Override - public ResWrap<Entity> toEntity(final InputStream input) throws ODataDeserializerException { - return deserializer.toEntity(input); - } - - @Override - public ResWrap<Property> toProperty(final InputStream input) throws ODataDeserializerException { - return deserializer.toProperty(input); - } - - @Override - public ODataError toError(final InputStream input) throws ODataDeserializerException { - return deserializer.toError(input); - } - - protected XmlMapper getXmlMapper() { - final XmlMapper xmlMapper = new XmlMapper( - new XmlFactory(new InputFactoryImpl(), new OutputFactoryImpl()), new JacksonXmlModule()); - - xmlMapper.setInjectableValues(new InjectableValues.Std().addValue(Boolean.class, Boolean.FALSE)); - - xmlMapper.addHandler(new DeserializationProblemHandler() { - @Override - public boolean handleUnknownProperty(final DeserializationContext ctxt, final JsonParser jp, - final com.fasterxml.jackson.databind.JsonDeserializer<?> deserializer, - final Object beanOrClass, final String propertyName) - throws IOException, JsonProcessingException { - - // skip any unknown property - ctxt.getParser().skipChildren(); - return true; - } - }); - return xmlMapper; - } - - @Override - public XMLMetadata toMetadata(final InputStream input) { - try { - return new ClientCsdlXMLMetadata(getXmlMapper().readValue(input, ClientCsdlEdmx.class)); - } catch (Exception e) { - throw new IllegalArgumentException("Could not parse as Edmx document", e); - } - } - - @Override - public ResWrap<ServiceDocument> toServiceDocument(final InputStream input) throws ODataDeserializerException { - return contentType.isCompatible(ContentType.APPLICATION_XML) ? - new XMLServiceDocumentDeserializer(false).toServiceDocument(input) : - new JSONServiceDocumentDeserializer(false).toServiceDocument(input); - } - - @Override - public ResWrap<Delta> toDelta(final InputStream input) throws ODataDeserializerException { - try { - return contentType.isCompatible(ContentType.APPLICATION_ATOM_SVC) - || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML) ? - new AtomDeserializer().delta(input) : - new JsonDeltaDeserializer(false).toDelta(input); - } catch (final XMLStreamException e) { - throw new ODataDeserializerException(e); - } catch (final EdmPrimitiveTypeException e) { - throw new ODataDeserializerException(e); - } - } - - @Override - public List<CsdlSchema> fetchTermDefinitionSchema(List<InputStream> input) { - List<CsdlSchema> schemas = new ArrayList<CsdlSchema>(); - try { - for (InputStream stream : input) { - ClientCsdlEdmx edmx = getXmlMapper().readValue(stream, ClientCsdlEdmx.class); - schemas.addAll(edmx.getDataServices().getSchemas()); - } - return schemas; - } catch (Exception e) { - throw new IllegalArgumentException("Could not parse Term definition", e); - } - } -} +/* + * 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.client.core.serialization; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLStreamException; + +import org.apache.olingo.client.api.data.ResWrap; +import org.apache.olingo.client.api.data.ServiceDocument; +import org.apache.olingo.client.api.edm.xml.Edmx; +import org.apache.olingo.client.api.edm.xml.XMLMetadata; +import org.apache.olingo.client.api.serialization.ClientODataDeserializer; +import org.apache.olingo.client.api.serialization.ODataDeserializer; +import org.apache.olingo.client.api.serialization.ODataDeserializerException; +import org.apache.olingo.client.core.data.JSONServiceDocumentDeserializer; +import org.apache.olingo.client.core.data.XMLServiceDocumentDeserializer; +import org.apache.olingo.client.core.edm.ClientCsdlXMLMetadata; +import org.apache.olingo.client.core.edm.xml.ClientCsdlEdmx; +import org.apache.olingo.commons.api.data.Delta; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; +import org.apache.olingo.commons.api.edm.provider.CsdlSchema; +import org.apache.olingo.commons.api.ex.ODataError; +import org.apache.olingo.commons.api.format.ContentType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import com.fasterxml.aalto.stax.InputFactoryImpl; +import com.fasterxml.aalto.stax.OutputFactoryImpl; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.InjectableValues; +import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; +import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; +import com.fasterxml.jackson.dataformat.xml.XmlFactory; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + +public class ClientODataDeserializerImpl implements ClientODataDeserializer { + + private final ODataDeserializer deserializer; + private final ContentType contentType; + private static final String SCHEMA = "Schema"; + private static final String XMLNS = "xmlns"; + + public ClientODataDeserializerImpl(final boolean serverMode, final ContentType contentType) { + this.contentType = contentType; + if (contentType.isCompatible(ContentType.APPLICATION_ATOM_SVC) + || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML) + || contentType.isCompatible(ContentType.APPLICATION_XML)) { + deserializer = new AtomDeserializer(); + } else { + deserializer = new JsonDeserializer(serverMode); + } + } + + @Override + public ResWrap<EntityCollection> toEntitySet(final InputStream input) throws ODataDeserializerException { + return deserializer.toEntitySet(input); + } + + @Override + public ResWrap<Entity> toEntity(final InputStream input) throws ODataDeserializerException { + return deserializer.toEntity(input); + } + + @Override + public ResWrap<Property> toProperty(final InputStream input) throws ODataDeserializerException { + return deserializer.toProperty(input); + } + + @Override + public ODataError toError(final InputStream input) throws ODataDeserializerException { + return deserializer.toError(input); + } + + protected XmlMapper getXmlMapper() { + final XmlMapper xmlMapper = new XmlMapper( + new XmlFactory(new InputFactoryImpl(), new OutputFactoryImpl()), new JacksonXmlModule()); + + xmlMapper.setInjectableValues(new InjectableValues.Std().addValue(Boolean.class, Boolean.FALSE)); + + xmlMapper.addHandler(new DeserializationProblemHandler() { + @Override + public boolean handleUnknownProperty(final DeserializationContext ctxt, final JsonParser jp, + final com.fasterxml.jackson.databind.JsonDeserializer<?> deserializer, + final Object beanOrClass, final String propertyName) + throws IOException, JsonProcessingException { + + // skip any unknown property + ctxt.getParser().skipChildren(); + return true; + } + }); + return xmlMapper; + } + + @Override + public XMLMetadata toMetadata(final InputStream input) { + try { + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + org.apache.commons.io.IOUtils.copy(input, byteArrayOutputStream); + // copy the content of input stream to reuse it + byte[] inputContent = byteArrayOutputStream.toByteArray(); + + InputStream inputStream1 = new ByteArrayInputStream(inputContent); + Edmx edmx = getXmlMapper().readValue(inputStream1, ClientCsdlEdmx.class); + + InputStream inputStream2 = new ByteArrayInputStream(inputContent); + List<List<String>> schemaNameSpaces = getAllSchemaNameSpace(inputStream2); + + return new ClientCsdlXMLMetadata(edmx,schemaNameSpaces); + } catch (Exception e) { + throw new IllegalArgumentException("Could not parse as Edmx document", e); + } + } + + private List<List<String>> getAllSchemaNameSpace(InputStream inputStream) + throws ParserConfigurationException, SAXException, IOException{ + List<List<String>> schemaNameSpaces = new ArrayList <List<String>>(); + + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + dbFactory.setFeature( + "http://xml.org/sax/features/namespaces", true); + dbFactory.setFeature( + "http://apache.org/xml/features/validation/schema", + false); + dbFactory.setFeature( + "http://apache.org/xml/features/validation/schema-full-checking", + true); + dbFactory.setFeature( + "http://xml.org/sax/features/external-general-entities", + false); + dbFactory.setFeature( + "http://xml.org/sax/features/external-parameter-entities", + false); + dbFactory.setFeature( + "http://apache.org/xml/features/disallow-doctype-decl", + true); + dbFactory.setFeature( + "http://javax.xml.XMLConstants/feature/secure-processing", + true); + + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(inputStream); + doc.getDocumentElement().normalize(); + NodeList nList = doc.getElementsByTagName(SCHEMA); + + for (int temp = 0; temp < nList.getLength(); temp++) { + Node nNode = nList.item(temp); + List<String> nameSpaces = new ArrayList <String>(); + if (nNode.getNodeType() == Node.ELEMENT_NODE) { + Element eElement = (Element) nNode; + NamedNodeMap attributes = eElement.getAttributes(); + int len = attributes.getLength(); + for(int i =0;i<len;i++){ + // check for all atributes begining with name xmlns or xmlns: + String attrName = attributes.item(i).getNodeName(); + if( XMLNS.equals(attrName) || attrName.startsWith(XMLNS+":")){ + nameSpaces.add(attributes.item(i).getNodeValue()); + } + } + } + schemaNameSpaces.add(nameSpaces); + } + return schemaNameSpaces; + } + + @Override + public ResWrap<ServiceDocument> toServiceDocument(final InputStream input) throws ODataDeserializerException { + return contentType.isCompatible(ContentType.APPLICATION_XML) ? + new XMLServiceDocumentDeserializer(false).toServiceDocument(input) : + new JSONServiceDocumentDeserializer(false).toServiceDocument(input); + } + + @Override + public ResWrap<Delta> toDelta(final InputStream input) throws ODataDeserializerException { + try { + return contentType.isCompatible(ContentType.APPLICATION_ATOM_SVC) + || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML) ? + new AtomDeserializer().delta(input) : + new JsonDeltaDeserializer(false).toDelta(input); + } catch (final XMLStreamException e) { + throw new ODataDeserializerException(e); + } catch (final EdmPrimitiveTypeException e) { + throw new ODataDeserializerException(e); + } + } + + @Override + public List<CsdlSchema> fetchTermDefinitionSchema(List<InputStream> input) { + List<CsdlSchema> schemas = new ArrayList<CsdlSchema>(); + try { + for (InputStream stream : input) { + ClientCsdlEdmx edmx = getXmlMapper().readValue(stream, ClientCsdlEdmx.class); + schemas.addAll(edmx.getDataServices().getSchemas()); + } + return schemas; + } catch (Exception e) { + throw new IllegalArgumentException("Could not parse Term definition", e); + } + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eea324d5/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataMetadataValidationImpl.java ---------------------------------------------------------------------- diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataMetadataValidationImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataMetadataValidationImpl.java index 325cf1f..acbb040 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataMetadataValidationImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataMetadataValidationImpl.java @@ -114,4 +114,14 @@ public class ODataMetadataValidationImpl implements ODataMetadataValidation { csdlEntityTypesMap, csdlComplexTypesMap, csdlActionsMap, csdlFunctionsMap); csdlTypeValidator.validateMetadataXML(); } + + @Override + public boolean isV4Metadata(XMLMetadata xmlMetadata) throws Exception{ + return new CsdlTypeValidator().isV4MetaData(xmlMetadata); + } + + @Override + public boolean isServiceDocument(XMLMetadata xmlMetadata){ + return new CsdlTypeValidator().isServiceDocument(xmlMetadata); + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/eea324d5/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataValidationTest.java ---------------------------------------------------------------------- diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataValidationTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataValidationTest.java index cec818e..32f61bf 100644 --- a/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataValidationTest.java +++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/MetadataValidationTest.java @@ -626,6 +626,61 @@ public class MetadataValidationTest extends AbstractTest { + "EntityType=\"Namespace2_Alias.ODataWebExperimentalETKeyNav\"/>" + "</EntityContainer></Schema></edmx:DataServices></edmx:Edmx>"; + public static final String V4MetadataWithNoEntityContainer ="<?xml version=\"1.0\" encoding=\"utf-8\"?>" + +"<edmx:Edmx Version=\"4.0\" xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\">" + + "<edmx:Reference Uri=\"../VOC_Core/$metadata\">" + + "<edmx:Include Namespace=\"Org.OData.Core.V1\" Alias=\"Core\" />" + + "</edmx:Reference>" + + "<edmx:DataServices>" + +"<Schema Namespace=\"EPMSample2\" xmlns=\"http://docs.oasis-open.org/odata/ns/edm\"/>" + + "</edmx:DataServices>" + +"</edmx:Edmx>"; + + public static final String invalidV4MetadataWithNoSchema ="<?xml version=\"1.0\" encoding=\"utf-8\"?>" + +"<edmx:Edmx Version=\"4.0\" xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\">" + + "<edmx:Reference Uri=\"../VOC_Core/$metadata\">" + + "<edmx:Include Namespace=\"Org.OData.Core.V1\" Alias=\"Core\" />" + + "</edmx:Reference>" + + "<edmx:DataServices>" + + "</edmx:DataServices>" + +"</edmx:Edmx>"; + + public static final String validMetadataWithMultipleSchemaNamespaces ="<?xml version=\"1.0\" encoding=\"utf-8\"?>" + +"<edmx:Edmx Version=\"4.0\" xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\" >" + + "<edmx:Reference Uri=\"../VOC_Core/$metadata\">" + + "<edmx:Include Namespace=\"Org.OData.Core.V1\" Alias=\"Core\" />" + + "</edmx:Reference>" + + "<edmx:DataServices>" + +"<Schema Namespace=\"EPMSample41\" xmlns:abc=\"http://docs.oasis-open.org/odata/ns/edm\" " + + "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\"/>" + +"<Schema Namespace=\"EPMSample42\" xmlns:xyz=\"http://docs.oasis-open.org/odata/ns/edm\"" + + " xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\"/>" + +"<Schema Namespace=\"EPMSample43\" xmlns=\"http://docs.oasis-open.org/odata/ns/edm\" " + + "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\"/>" + + "</edmx:DataServices>" + +"</edmx:Edmx>"; + + public static final String invalidV4MetadataWithV2Schemas ="<?xml version=\"1.0\" encoding=\"utf-8\"?>" + +"<edmx:Edmx Version=\"4.0\" xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\">" + + "<edmx:Reference Uri=\"../VOC_Core/$metadata\">" + + "<edmx:Include Namespace=\"Org.OData.Core.V1\" Alias=\"Core\" />" + + "</edmx:Reference>" + + "<edmx:DataServices>" + +"<Schema Namespace=\"EPMSample2\" xmlns=\"http://schemas.microsoft.com/ado/2008/09/edm\"/>" + +"<Schema Namespace=\"EPM2\" xmlns=\"http://schemas.microsoft.com/ado/2008/09/edm\"/>" + + "</edmx:DataServices>" + +"</edmx:Edmx>"; + public static final String invalidV4MetadataWithV2AndV4Schemas ="<?xml version=\"1.0\" encoding=\"utf-8\"?>" + +"<edmx:Edmx Version=\"4.0\" xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\">" + + "<edmx:Reference Uri=\"../VOC_Core/$metadata\">" + + "<edmx:Include Namespace=\"Org.OData.Core.V1\" Alias=\"Core\" />" + + "</edmx:Reference>" + + "<edmx:DataServices>" + +"<Schema Namespace=\"EPMSample4\" xmlns=\"http://docs.oasis-open.org/odata/ns/edm\"/>" + +"<Schema Namespace=\"EPM2\" xmlns=\"http://schemas.microsoft.com/ado/2008/09/edm\"/>" + + "</edmx:DataServices>" + +"</edmx:Edmx>"; + @Test public void testXMLMetadataWithOneSchema() { final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). @@ -645,6 +700,121 @@ public class MetadataValidationTest extends AbstractTest { } @Test + public void checkValidV4XMLMetadataWithTwoSchemas() { + final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). + toMetadata(getClass().getResourceAsStream("northwind-metadata.xml")); + assertNotNull(metadata); + ODataMetadataValidation metadataValidator = client.metadataValidation(); + try { + assertEquals(true,metadataValidator.isV4Metadata(metadata)); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void checkInValidV4XMLMetadataWithTwoSchemas() { + + boolean checkException = false; + try { + InputStream stream = new ByteArrayInputStream(invalidV4MetadataWithV2AndV4Schemas.getBytes("UTF-8")); + final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). + toMetadata(stream); + assertNotNull(metadata); + ODataMetadataValidation metadataValidator = client.metadataValidation(); + assertEquals(false,metadataValidator.isV4Metadata(metadata)); + + } catch (Exception e) { + checkException = true; + + } + assertEquals(false,checkException); + } + + @Test + public void checkInValidV4XMLMetadataWithNoSchemas() { + boolean checkException = false; + try { + InputStream stream = new ByteArrayInputStream(invalidV4MetadataWithNoSchema.getBytes("UTF-8")); + final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). + toMetadata(stream); + assertNotNull(metadata); + ODataMetadataValidation metadataValidator = client.metadataValidation(); + metadataValidator.isV4Metadata(metadata); + + } catch (Exception e) { + checkException = true; + assertEquals(e.getMessage(), "Cannot determine if v4 metadata," + + "No schemanamespaces found in XMLMetadata"); + } + assertEquals(true,checkException); + } + + + @Test + public void checkInValidV4XMLMetadataWithNoSchemasample() { + boolean checkException = false; + try { + InputStream stream = new ByteArrayInputStream(validMetadataWithMultipleSchemaNamespaces.getBytes("UTF-8")); + final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). + toMetadata(stream); + assertNotNull(metadata); + ODataMetadataValidation metadataValidator = client.metadataValidation(); + assertEquals(true,metadataValidator.isV4Metadata(metadata)); + + } catch (Exception e) { + checkException = true; + + } + assertEquals(false,checkException); + } + + @Test + public void checkInValidV4XMLMetadataWithV2Schemas() { + + try { + InputStream stream = new ByteArrayInputStream(invalidV4MetadataWithV2Schemas.getBytes("UTF-8")); + final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). + toMetadata(stream); + assertNotNull(metadata); + ODataMetadataValidation metadataValidator = client.metadataValidation(); + assertEquals(false,metadataValidator.isV4Metadata(metadata)); + + } catch (Exception e) { + + assertEquals(false, true); + } + } + + + + @Test + public void testIfV4Service() { + final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). + toMetadata(getClass().getResourceAsStream("northwind-metadata.xml")); + assertNotNull(metadata); + ODataMetadataValidation metadataValidator = client.metadataValidation(); + assertEquals(true,metadataValidator.isServiceDocument(metadata)); + } + + @Test + public void testIfV4ServiceWithNoEntityContainer() { + try{ + InputStream stream = new ByteArrayInputStream(V4MetadataWithNoEntityContainer.getBytes("UTF-8")); + final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). + toMetadata(stream); + assertNotNull(metadata); + ODataMetadataValidation metadataValidator = client.metadataValidation(); + boolean isservice = metadataValidator.isServiceDocument(metadata); + assertEquals(false,isservice); + }catch (Exception e) { + + assertEquals(false, true); + } + + } + @Test public void testXMLMetadataWithTripInService() { final XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML). toMetadata(getClass().getResourceAsStream("metadata_TripInService.xml"));
