Repository: olingo-odata4 Updated Branches: refs/heads/master d9aff6300 -> fd8bfa33d
OLINGO-1252: adding ability load reference schemas recursively, but locallized to the schema they represent Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/fd8bfa33 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/fd8bfa33 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/fd8bfa33 Branch: refs/heads/master Commit: fd8bfa33d485e6ea158025d468a009cd8bfc19ff Parents: d9aff63 Author: Ramesh Reddy <rare...@jboss.org> Authored: Thu Apr 5 12:41:42 2018 -0500 Committer: Ramesh Reddy <rare...@jboss.org> Committed: Thu Apr 5 12:41:42 2018 -0500 ---------------------------------------------------------------------- .../olingo/server/core/MetadataParser.java | 59 ++++++++++------ .../server/core/SchemaBasedEdmProvider.java | 48 +++++++------ .../olingo/server/core/MetadataParserTest.java | 73 ++++++++++++++++---- 3 files changed, 122 insertions(+), 58 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fd8bfa33/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java index 88b8ad2..63b33d7 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java @@ -27,6 +27,8 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; @@ -100,7 +102,8 @@ public class MetadataParser { private ReferenceResolver referenceResolver = new DefaultReferenceResolver(); private boolean useLocalCoreVocabularies = true; private boolean implicitlyLoadCoreVocabularies = false; - private boolean recusivelyLoadReferences = false; + private boolean recursivelyLoadReferences = false; + private Map<String, SchemaBasedEdmProvider> globalReferenceMap = new HashMap<String, SchemaBasedEdmProvider>(); /** * Avoid reading the annotations in the $metadata @@ -138,7 +141,7 @@ public class MetadataParser { * @return */ public MetadataParser recursivelyLoadReferences(boolean load) { - this.recusivelyLoadReferences = load; + this.recursivelyLoadReferences = load; return this; } @@ -154,35 +157,37 @@ public class MetadataParser { public ServiceMetadata buildServiceMetadata(Reader csdl) throws XMLStreamException { SchemaBasedEdmProvider provider = buildEdmProvider(csdl, this.referenceResolver, - this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies, true); + this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies, true, null); return new ServiceMetadataImpl(provider, provider.getReferences(), null); } public SchemaBasedEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException { XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl); - return buildEdmProvider(reader, this.referenceResolver, - this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies, true); + return buildEdmProvider(reader, this.referenceResolver, this.implicitlyLoadCoreVocabularies, + this.useLocalCoreVocabularies, true, null); } - protected SchemaBasedEdmProvider buildEdmProvider(Reader csdl, - ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas) - throws XMLStreamException { + protected SchemaBasedEdmProvider buildEdmProvider(Reader csdl, ReferenceResolver resolver, + boolean loadCore, boolean useLocal, + boolean loadReferenceSchemas, String namespace) + throws XMLStreamException { XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); - XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl); - return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas); + XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl); + return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas, namespace); } - - protected SchemaBasedEdmProvider buildEdmProvider(InputStream csdl, - ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas) - throws XMLStreamException { + + protected SchemaBasedEdmProvider buildEdmProvider(InputStream csdl, ReferenceResolver resolver, + boolean loadCore, boolean useLocal, + boolean loadReferenceSchemas, String namespace) + throws XMLStreamException { XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl); - return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas); + return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas, namespace); } protected SchemaBasedEdmProvider buildEdmProvider(XMLEventReader reader, - ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas) + ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas, String namespace) throws XMLStreamException { SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider(); @@ -220,7 +225,11 @@ public class MetadataParser { loadCoreVocabulary(provider, "Org.OData.Capabilities.V1"); loadCoreVocabulary(provider, "Org.OData.Measures.V1"); } - + + if (namespace != null && !namespace.equals("") && !globalReferenceMap.containsKey(namespace)) { + globalReferenceMap.put(namespace, provider); + } + // load all the reference schemas if (resolver != null && loadReferenceSchemas) { loadReferencesSchemas(provider, xmlBase.length() == 0 ? null @@ -239,8 +248,8 @@ public class MetadataParser { for (EdmxReferenceInclude include : reference.getIncludes()) { - // check if the schema is already loaded before. - if (provider.getSchema(include.getNamespace()) != null) { + // check if the schema is already loaded before in current provider. + if (provider.getSchemaDirectly(include.getNamespace()) != null) { continue; } @@ -248,15 +257,19 @@ public class MetadataParser { loadCoreVocabulary(provider, include.getNamespace()); continue; } - + + // check if the schema is already loaded before in parent providers + refProvider = this.globalReferenceMap.get(include.getNamespace()); + if (refProvider == null) { InputStream is = this.referenceResolver.resolveReference(reference.getUri(), xmlBase); if (is == null) { throw new EdmException("Failed to load Reference "+reference.getUri()+" loading failed"); } else { // do not implicitly load core vocabularies any more. But if the - // references loading the core vocabularies try to use local if we can - refProvider = buildEdmProvider(is, resolver, false, useLocal, this.recusivelyLoadReferences); + // references loading the core vocabularies try to use local if we can + refProvider = buildEdmProvider(is, resolver, false, useLocal, + this.recursivelyLoadReferences, include.getNamespace()); } } @@ -308,7 +321,7 @@ public class MetadataParser { if (schema == null) { InputStream is = this.getClass().getClassLoader().getResourceAsStream(resource); if (is != null) { - SchemaBasedEdmProvider childProvider = buildEdmProvider(is, null, false, false, true); + SchemaBasedEdmProvider childProvider = buildEdmProvider(is, null, false, false, true, ""); provider.addVocabularySchema(namespace, childProvider); } else { throw new XMLStreamException("failed to load "+resource+" core vocabulary"); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fd8bfa33/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java index 128aecb..e11cffc 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java @@ -19,8 +19,10 @@ package org.apache.olingo.server.core; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.olingo.commons.api.edm.FullQualifiedName; @@ -88,38 +90,44 @@ public class SchemaBasedEdmProvider implements CsdlEdmProvider { } CsdlSchema getSchema(String ns, boolean checkReferences) { + if (checkReferences) { + return getSchemaRecursively(ns, new HashSet<String>()); + } else { + return getSchemaDirectly(ns); + } + } + + CsdlSchema getSchemaDirectly(String ns) { for (CsdlSchema s : this.edmSchemas) { if (s.getNamespace().equals(ns)) { return s; } } - CsdlSchema s = null; - if (checkReferences) { - s = getReferenceSchema(ns); - if (s == null) { - s = getVocabularySchema(ns); - } - } - return s; + return null; } - CsdlSchema getReferenceSchema(String ns) { - if (ns == null) { - return null; - } - - if (this.referenceSchemas.get(ns) != null) { - return this.referenceSchemas.get(ns).getSchema(ns); + CsdlSchema getSchemaRecursively(String ns, Set<String> parsedPath) { + // find the schema by namespace in current provider + CsdlSchema schema = getSchemaDirectly(ns); + if (schema != null) { + return schema; } - - // it is possible that we may be looking for Reference schema of Reference - for (SchemaBasedEdmProvider provider:this.referenceSchemas.values()) { - CsdlSchema schema = provider.getSchema(ns); + + // find the schema by namespace in the reference schema provider + for (Map.Entry<String, SchemaBasedEdmProvider> entry : this.referenceSchemas.entrySet()) { + String namespace = entry.getKey(); + if (parsedPath.contains(namespace)) { + continue; + } + SchemaBasedEdmProvider provider = entry.getValue(); + parsedPath.add(namespace); + schema = provider.getSchemaRecursively(ns, parsedPath); if (schema != null) { return schema; } } - return null; + + return getVocabularySchema(ns); } @Override http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fd8bfa33/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java index a0e6aeb..c3e67e0 100644 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java @@ -46,6 +46,7 @@ import org.apache.olingo.commons.api.edm.provider.CsdlNavigationPropertyBinding; import org.apache.olingo.commons.api.edm.provider.CsdlParameter; import org.apache.olingo.commons.api.edm.provider.CsdlProperty; import org.apache.olingo.commons.api.edm.provider.CsdlSingleton; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -56,6 +57,21 @@ public class MetadataParserTest { CsdlEdmProvider provider = null; + ReferenceResolver testReferenceResolver = new ReferenceResolver() { + @Override + public InputStream resolveReference(URI uri, String xmlBase) { + String str = uri.toASCIIString(); + if (str.startsWith("http://localhost/")) { + try { + return new FileInputStream("src/test/resources/"+str.substring(17)); + } catch (FileNotFoundException e) { + return null; + } + } + return null; + } + }; + @Before public void setUp() throws Exception { MetadataParser parser = new MetadataParser(); @@ -197,20 +213,47 @@ public class MetadataParserTest { public void testReferenceLoad() throws Exception { MetadataParser parser = new MetadataParser(); parser.recursivelyLoadReferences(false); - parser.referenceResolver(new ReferenceResolver() { - @Override - public InputStream resolveReference(URI uri, String xmlBase) { - String str = uri.toASCIIString(); - if (str.startsWith("http://localhost/")) { - try { - return new FileInputStream("src/test/resources/"+str.substring(17)); - } catch (FileNotFoundException e) { - return null; - } - } - return null; - } - }); + parser.referenceResolver(this.testReferenceResolver); provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/test.xml")); - } + } + + @Test + public void testReferenceLoadRecursively() throws Exception { + MetadataParser parser = new MetadataParser(); + parser.recursivelyLoadReferences(true); + parser.referenceResolver(testReferenceResolver); + SchemaBasedEdmProvider providerTest = parser.buildEdmProvider(new FileReader("src/test/resources/test.xml")); + + Assert.assertNotNull(providerTest.getSchema("Microsoft.OData.SampleService.Models.TripPin", false)); + + Assert.assertNull(providerTest.getSchema("org.apache.olingo.a", false)); + Assert.assertNull(providerTest.getSchema("org.apache.olingo.b", false)); + + Assert.assertNotNull(providerTest.getSchema("org.apache.olingo.a", true)); + Assert.assertNotNull(providerTest.getSchema("org.apache.olingo.b", true)); + } + + @Test + public void testCircleReferenceShouldNotStackOverflow() throws Exception { + MetadataParser parser = new MetadataParser(); + parser.recursivelyLoadReferences(true); + parser.referenceResolver(testReferenceResolver); + SchemaBasedEdmProvider providerTest = parser.buildEdmProvider(new FileReader("src/test/resources/test.xml")); + + Assert.assertNull(providerTest.getSchema("Not Found", true)); + + + } + + @Test + public void testLoadCoreVocabulary() throws Exception { + MetadataParser parser = new MetadataParser(); + parser.implicitlyLoadCoreVocabularies(true); + parser.referenceResolver(testReferenceResolver); + SchemaBasedEdmProvider provider = parser.buildEdmProvider(new FileReader("src/test/resources/test.xml")); + + Assert.assertNotNull(provider.getVocabularySchema("Org.OData.Core.V1")); + Assert.assertNotNull(provider.getSchema("Org.OData.Core.V1")); + + } }