OLINGO-878: Adding support to remove invalid xml characters from Atom payload
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/a8d1d4c6 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/a8d1d4c6 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/a8d1d4c6 Branch: refs/heads/OLINGO-856_ODataHandlerInAPI Commit: a8d1d4c647225671dc45f0297789e7a5b45479f0 Parents: 3c205f9 d880d6c Author: Ramesh Reddy <[email protected]> Authored: Fri Feb 12 19:44:36 2016 -0600 Committer: Ramesh Reddy <[email protected]> Committed: Mon Feb 15 12:31:34 2016 -0600 ---------------------------------------------------------------------- .../core/edm/annotation/EdmRecordImpl.java | 16 +- .../core/edm/annotations/EdmRecordImplTest.java | 6 - .../serializer/ComplexSerializerOptions.java | 14 +- .../EntityCollectionSerializerOptions.java | 14 +- .../api/serializer/EntitySerializerOptions.java | 14 +- .../serializer/PrimitiveSerializerOptions.java | 13 + .../PrimitiveValueSerializerOptions.java | 14 +- .../olingo/server/core/MetadataParser.java | 262 ++++++++++++++----- .../server/core/SchemaBasedEdmProvider.java | 117 ++++----- .../olingo/server/core/ServiceRequest.java | 50 +++- .../server/core/requests/DataRequest.java | 13 +- .../src/main/resources/org.apache.olingo.v1.xml | 40 +++ .../core/MetadataParserAnnotationsTest.java | 10 +- .../olingo/server/core/MetadataParserTest.java | 1 - .../server/core/ServiceDispatcherTest.java | 3 + .../olingo/server/example/TripPinHandler.java | 1 + .../server/example/TripPinServiceTest.java | 30 ++- .../olingo/server/example/TripPinServlet.java | 3 +- .../src/test/resources/airlines.json | 2 +- .../src/test/resources/annotations.xml | 17 ++ .../src/test/resources/trippin.xml | 6 +- .../xml/MetadataDocumentXmlSerializer.java | 5 +- .../core/serializer/xml/ODataXmlSerializer.java | 138 ++++++---- .../serializer/xml/ODataXmlSerializerTest.java | 27 +- 24 files changed, 594 insertions(+), 222 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/annotation/EdmRecordImpl.java ---------------------------------------------------------------------- diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/annotation/EdmRecordImpl.java index 919f189,919f189..811f82b --- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/annotation/EdmRecordImpl.java +++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/annotation/EdmRecordImpl.java @@@ -59,14 -59,14 +59,14 @@@ public class EdmRecordImpl extends Abst @Override public EdmStructuredType getType() { if (type == null) { -- if (record.getType() == null) { -- throw new EdmException("Must specify a type for a Record expression."); -- } -- final EdmTypeInfo typeInfo = new EdmTypeInfo.Builder().setEdm(edm).setTypeExpression(record.getType()).build(); -- if (typeInfo.isEntityType() || typeInfo.isComplexType()) { -- type = typeInfo.isEntityType() ? typeInfo.getEntityType() : typeInfo.getComplexType(); -- } else { -- throw new EdmException("Record expressions must specify a complex or entity type."); ++ // record MAY have a type information. ++ if (record.getType() != null) { ++ final EdmTypeInfo typeInfo = new EdmTypeInfo.Builder().setEdm(edm).setTypeExpression(record.getType()).build(); ++ if (typeInfo.isEntityType() || typeInfo.isComplexType()) { ++ type = typeInfo.isEntityType() ? typeInfo.getEntityType() : typeInfo.getComplexType(); ++ } else { ++ throw new EdmException("Record expressions must specify a complex or entity type."); ++ } } } return type; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/annotations/EdmRecordImplTest.java ---------------------------------------------------------------------- diff --cc lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/annotations/EdmRecordImplTest.java index ddae8bc,ddae8bc..8076ffb --- a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/annotations/EdmRecordImplTest.java +++ b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/annotations/EdmRecordImplTest.java @@@ -63,12 -63,12 +63,6 @@@ public class EdmRecordImplTest extends assertSingleKindDynamicExpression(dynExp); EdmRecord asRecord = dynExp.asRecord(); -- try { -- asRecord.getType(); -- fail("EdmException expected"); -- } catch (EdmException e) { -- assertEquals("Must specify a type for a Record expression.", e.getMessage()); -- } assertNotNull(asRecord.getAnnotations()); assertTrue(asRecord.getAnnotations().isEmpty()); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java ---------------------------------------------------------------------- diff --cc lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java index 03a6675,b93ef4c..c47aa52 --- 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 @@@ -191,8 -304,9 +304,8 @@@ public class MetadataParser } private void readDataServicesAndReference(XMLEventReader reader, - StartElement element, SchemaBasedEdmProvider provider) throws XMLStreamException { - final ArrayList<EdmxReference> references = new ArrayList<EdmxReference>(); + StartElement element, SchemaBasedEdmProvider provider) + throws XMLStreamException { - final ArrayList<EdmxReference> references = new ArrayList<EdmxReference>(); new ElementReader<SchemaBasedEdmProvider>() { @Override void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider, @@@ -200,15 -314,15 +313,14 @@@ if (name.equals("DataServices")) { readSchema(reader, element, provider); } else if (name.equals("Reference")) { -- readReference(reader, element, references, "Reference"); ++ readReference(reader, element, provider, "Reference"); } } }.read(reader, element, provider, "DataServices", "Reference"); -- provider.addReferences(references); } private void readReference(XMLEventReader reader, StartElement element, -- final ArrayList<EdmxReference> references, String name) throws XMLStreamException { ++ final SchemaBasedEdmProvider provider, String name) throws XMLStreamException { EdmxReference reference; try { String uri = attr(element, "Uri"); @@@ -235,7 -349,7 +347,7 @@@ } } }.read(reader, element, reference, "Include", "IncludeAnnotations", "Annotation"); -- references.add(reference); ++ provider.addReference(reference); } private void readSchema(XMLEventReader reader, StartElement element, @@@ -447,7 -563,7 +561,7 @@@ final CsdlAnnotations annotations = new CsdlAnnotations(); annotations.setTarget(attr(element, "Target")); annotations.setQualifier(attr(element, "Qualifier")); -- readAnnotations(reader, element, annotations); ++ peekAnnotations(reader, element.getName().getLocalPart(), annotations); schema.getAnnotationGroups().add(annotations); } @@@ -540,24 -656,24 +654,8 @@@ void build(XMLEventReader reader, StartElement element, T target, String name) throws XMLStreamException { -- // attribute based expressions -- if (attr(element, "AnnotationPath") != null) { -- write(target, new CsdlAnnotationPath().setValue(attr(element, "AnnotationPath"))); -- } -- if (attr(element, "NavigationPropertyPath") != null) { -- write(target, new CsdlNavigationPropertyPath() -- .setValue(attr(element, "NavigationPropertyPath"))); -- } -- if (attr(element, "Path") != null) { -- write(target, new CsdlPath().setValue(attr(element, "Path"))); -- } -- if (attr(element, "PropertyPath") != null) { -- write(target, new CsdlPropertyPath().setValue(attr(element, "PropertyPath"))); -- } -- if (attr(element, "UrlRef") != null) { -- write(target, new CsdlUrlRef().setValue(new CsdlConstantExpression( -- ConstantExpressionType.String, attr(element, "UrlRef")))); -- } ++ // attribute based expressions. ++ readAttributeExpressions(element, target); // element based expressions for (ConstantExpressionType type:ConstantExpressionType.values()) { @@@ -567,7 -683,7 +665,8 @@@ write(target, expr); } } -- } ++ } ++ if (name.equals("Collection")) { CsdlCollection expr = new CsdlCollection(); readExpressions(reader, element, expr); @@@ -630,6 -746,6 +729,35 @@@ "Int", "String", "TimeOfDay"); } ++ private <T> void readAttributeExpressions(StartElement element, T target) ++ throws XMLStreamException { ++ // attribute based expressions ++ for (ConstantExpressionType type:ConstantExpressionType.values()) { ++ if (attr(element, type.name()) != null) { ++ write(target, new CsdlConstantExpression( ++ type, attr(element, type.name()))); ++ } ++ } ++ ++ if (attr(element, "AnnotationPath") != null) { ++ write(target, new CsdlAnnotationPath().setValue(attr(element, "AnnotationPath"))); ++ } ++ if (attr(element, "NavigationPropertyPath") != null) { ++ write(target, new CsdlNavigationPropertyPath() ++ .setValue(attr(element, "NavigationPropertyPath"))); ++ } ++ if (attr(element, "Path") != null) { ++ write(target, new CsdlPath().setValue(attr(element, "Path"))); ++ } ++ if (attr(element, "PropertyPath") != null) { ++ write(target, new CsdlPropertyPath().setValue(attr(element, "PropertyPath"))); ++ } ++ if (attr(element, "UrlRef") != null) { ++ write(target, new CsdlUrlRef().setValue(new CsdlConstantExpression( ++ ConstantExpressionType.String, attr(element, "UrlRef")))); ++ } ++ } ++ private String elementValue(XMLEventReader reader, StartElement element) throws XMLStreamException { while (reader.hasNext()) { XMLEvent event = reader.peek(); @@@ -655,6 -771,6 +783,7 @@@ throws XMLStreamException { CsdlPropertyValue value = new CsdlPropertyValue(); value.setProperty(attr(element, "Property")); ++ readAttributeExpressions(element, value); readExpressions(reader, element, value); record.getPropertyValues().add(value); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java ---------------------------------------------------------------------- diff --cc lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java index a778e2c,8aea555..a6445a7 --- 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 @@@ -68,7 -60,23 +60,29 @@@ public class SchemaBasedEdmProvider imp List<EdmxReference> getReferences(){ return new ArrayList<EdmxReference>(references.values()); } - + + void addReferenceSchema(String ns, SchemaBasedEdmProvider provider) { + this.referenceSchemas.put(ns, provider); + } + + void addVocabularySchema(String ns, SchemaBasedEdmProvider provider) { + this.coreVocabularySchemas.put(ns, provider); + } + ++ void addReference(EdmxReference reference) { ++ for (EdmxReferenceInclude include : reference.getIncludes()) { ++ this.references.put(include.getNamespace(), reference); ++ } ++ } ++ + CsdlSchema getVocabularySchema(String ns) { + SchemaBasedEdmProvider provider = this.coreVocabularySchemas.get(ns); + if (provider != null) { + return provider.getSchema(ns, false); + } + return null; + } + CsdlSchema getSchema(String ns) { return getSchema(ns, true); } @@@ -315,6 -297,6 +303,16 @@@ } } } ++ for (SchemaBasedEdmProvider p:this.coreVocabularySchemas.values()) { ++ for (CsdlSchema s:p.getSchemas()) { ++ if (s.getAlias() != null) { ++ CsdlAliasInfo ai = new CsdlAliasInfo(); ++ ai.setAlias(s.getAlias()); ++ ai.setNamespace(s.getNamespace()); ++ list.add(ai); ++ } ++ } ++ } return list; } @@@ -386,31 -368,21 +384,8 @@@ public CsdlAnnotations getAnnotationsGroup(FullQualifiedName targetName, String qualifier) throws ODataException { CsdlSchema schema = getSchema(targetName.getNamespace()); if (schema != null) { -- return schema.getAnnotationGroup(targetName.getName(), qualifier); ++ return schema.getAnnotationGroup(targetName.getFullQualifiedNameAsString(), qualifier); } return null; -- } -- -- void addReferences(ArrayList<EdmxReference> references) { -- if (references != null && !references.isEmpty()) { -- for (EdmxReference ref:references) { -- for (EdmxReferenceInclude include : ref.getIncludes()) { -- if (include.getAlias() != null) { -- this.references.put(include.getAlias(), ref); -- } -- this.references.put(include.getNamespace(), ref); -- } - } - } - } - - public void setXMLBase(String base) { - if (base != null) { - if (base.endsWith("/")) { - this.xmlBase = base; - } else { - this.xmlBase = base+"/"; -- } -- } } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java ---------------------------------------------------------------------- diff --cc lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java index d71c54d,75c12ad..0c6288a --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java @@@ -27,6 -27,6 +27,7 @@@ import java.util.Arrays import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation; ++import org.apache.olingo.commons.api.edm.provider.CsdlAnnotations; import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; import org.apache.olingo.commons.api.edm.provider.CsdlSchema; import org.apache.olingo.commons.api.edm.provider.CsdlTerm; @@@ -211,5 -211,5 +212,12 @@@ public class MetadataParserAnnotationsT public void checkCoreVocabularies() throws ODataException { CsdlTerm term = this.provider.getTerm(new FullQualifiedName("Org.OData.Core.V1", "Description")); assertEquals("Edm.String", term.getType()); ++ } ++ ++ @Test ++ public void testAnnotationGroup() throws ODataException { ++ CsdlAnnotations annotations = this.provider.getAnnotationsGroup( ++ new FullQualifiedName("Org.OData.AnnoatationTest.TagX"), null); ++ assertEquals(3, annotations.getAnnotations().size()); } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java ---------------------------------------------------------------------- diff --cc lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java index 4d2dbb9,4d2dbb9..c2ca7a6 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java @@@ -566,6 -566,6 +566,7 @@@ public class TripPinHandler implements @Override public void processError(ODataServerError error, ErrorResponse response) { ++ error.getException().printStackTrace(); response.writeError(error); } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java ---------------------------------------------------------------------- diff --cc lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java index 3beb274,ec0c7c7..114a1f3 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java @@@ -114,21 -114,24 +114,31 @@@ public class TripPinServiceTest } @Test - public void testEntitySet() throws Exception { - HttpRequest req = new HttpGet(baseURL+"/People"); - req.setHeader("Content-Type", "application/json;odata.metadata=minimal"); + public void testXMLInvalidChars() throws Exception { + HttpRequest req = new HttpGet(baseURL+"/Airlines('FM')"); + req.setHeader("Accept", "application/xml"); HttpResponse response = httpSend(req, 200); - JsonNode node = getJSONNode(response); - - assertEquals("$metadata#People", node.get("@odata.context").asText()); - assertEquals(baseURL+"/People?$skiptoken=8", node.get("@odata.nextLink").asText()); - - JsonNode person = ((ArrayNode)node.get("value")).get(0); - assertEquals("russellwhyte", person.get("UserName").asText()); + String actual = IOUtils.toString(response.getEntity().getContent()); + String expected = + "<m:properties>" + + "<d:AirlineCode>FM</d:AirlineCode>" + + "<d:Name>Shanghai xxxAirlinexxx</d:Name>" + + "<d:Picture m:null=\"true\"/>" + + "</m:properties>" + + "</a:content>" + +"</a:entry>"; + assertTrue(actual.endsWith(expected)); } + + @Test ++ public void testmetadata() throws Exception { ++ HttpRequest req = new HttpGet(baseURL+"/$metadata"); ++ HttpResponse response = httpSend(req, 200); ++ IOUtils.toString(response.getEntity().getContent()); ++ } + + @Test public void testReadEntitySetWithPaging() throws Exception { String url = baseURL+"/People"; HttpRequest request = new HttpGet(url); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/server-core-ext/src/test/resources/annotations.xml ---------------------------------------------------------------------- diff --cc lib/server-core-ext/src/test/resources/annotations.xml index 1c5281a,3c8570f..ca581f0 --- a/lib/server-core-ext/src/test/resources/annotations.xml +++ b/lib/server-core-ext/src/test/resources/annotations.xml @@@ -148,6 -151,6 +151,20 @@@ </Apply> </UrlRef> </Annotation> ++ <TypeDefinition Name="TagX" UnderlyingType="Edm.Boolean"> ++ <Annotation Term="Core.Description" String="This is the type to use for all tagging terms" /> ++ </TypeDefinition> ++ <Annotations ++ Target="Org.OData.AnnoatationTest.TagX"> ++ <Annotation Term="Org.OData.Core.V1.DereferenceableIDs" ++ Bool="true" /> ++ <Annotation Term="Org.OData.Core.V1.ConventionalIDs" ++ Bool="true" /> ++ <Annotation Term="Org.OData.Capabilities.V1.ConformanceLevel"> ++ <EnumMember>Org.OData.Capabilities.V1.ConformanceLevelType/Advanced ++ </EnumMember> ++ </Annotation> ++ </Annotations> </Schema> </edmx:DataServices> </edmx:Edmx> http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a8d1d4c6/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java ---------------------------------------------------------------------- diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java index a0fd021,a0fd021..55c7ede --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java @@@ -450,7 -450,7 +450,10 @@@ public class MetadataDocumentXmlSeriali break; case Record: EdmRecord asRecord = dynExp.asRecord(); -- writer.writeAttribute(XML_TYPE, getAliasedFullQualifiedName(asRecord.getType(), false)); ++ EdmStructuredType type = asRecord.getType(); ++ if (type != null) { ++ writer.writeAttribute(XML_TYPE, getAliasedFullQualifiedName(type, false)); ++ } for (EdmPropertyValue propValue : asRecord.getPropertyValues()) { writer.writeStartElement(XML_PROPERTY_Value); writer.writeAttribute(XML_PROPERTY, propValue.getProperty());
