Repository: olingo-odata4 Updated Branches: refs/heads/master fd71b7ebd -> 53881c2ac
[OLINGO-663] Generic Precondition Required Handling Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/53881c2a Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/53881c2a Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/53881c2a Branch: refs/heads/master Commit: 53881c2acf6f725b3e2d631ef083baf3cb225525 Parents: fd71b7e Author: Christian Amend <[email protected]> Authored: Mon Jun 1 13:52:52 2015 +0200 Committer: Christian Amend <[email protected]> Committed: Mon Jun 1 13:58:10 2015 +0200 ---------------------------------------------------------------------- .../olingo/server/api/CustomETagSupport.java | 32 ++- .../core/PreconditionRequiredException.java | 3 +- .../server/core/PreconditionsValidator.java | 112 +++++----- .../olingo/server/tecsvc/ETagSupport.java | 19 +- .../server/core/PreconditionsValidatorTest.java | 211 +++++++++++++++---- 5 files changed, 264 insertions(+), 113 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java index 2644b28..5e4f500 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java @@ -18,6 +18,8 @@ */ package org.apache.olingo.server.api; +import org.apache.olingo.commons.api.edm.EdmBindingTarget; + /** * <p>Processors that would like to support etags for certain entity sets can implement this * interface.</p> @@ -32,19 +34,41 @@ public interface CustomETagSupport { * If this method returns true and an header is not specified we will return a "Precondition Required" response. * Validation has to be performed inside the processor methods after the dispatching. * If this method returns false and an header is specified we will ignore the header. - * @param entitySetName + * @param entitySetOrSingleton * @return true if the entity set specified needs an if-match/if-none-match header */ - boolean hasETag(String entitySetName); + boolean hasETag(EdmBindingTarget entitySetOrSingleton); /** * This method will be called for update requests which target a media entity value. * If this method returns true and an header is not specified we will return a "Precondition Required" response. * Validation has to be performed inside the processor methods after the dispatching. * If this method returns false and an header is specified we will ignore the header. - * @param entitySetName + * @param entitySetOrSingleton * @return true if the entity set specified needs an if-match/if-none-match header */ - boolean hasMediaETag(String entitySetName); + boolean hasMediaETag(EdmBindingTarget entitySetOrSingleton); + + /** + * Since the Olingo library cannot generate a metadata document etag in a generic way we call this method to retrieve + * an application specific etag for the metadata document. If this interface is registered applications can return an + * etag or null here to provide caching support for clients. If a client sends a GET request to the metadata document + * and this method delivers an etag we will match it to the request. If there has been no modification we will return + * a 304 NOT MODIFIED status code. If this interface is not registered or delivers null we just send back the usual + * metadata response. + * @return the application generated etag for the metadata document + */ + String getMetadataETag(); + + /** + * Since the Olingo library cannot generate a service document etag in a generic way we call this method to retrieve + * an application specific etag for the service document. If this interface is registered applications can return an + * etag or null here to provide caching support for clients. If a client sends a GET request to the service document + * and this method delivers an etag we will match it to the request. If there has been no modification we will return + * a 304 NOT MODIFIED status code. If this interface is not registered or delivers null we just send back the usual + * service document response. + * @return the application generated etag for the service document + */ + String getServiceDocumentETag(); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java index 4fb527f..c42f7df 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java @@ -24,7 +24,8 @@ public class PreconditionRequiredException extends ODataTranslatedException { private static final long serialVersionUID = -8112658467394158700L; public static enum MessageKeys implements MessageKey { - MISSING_HEADER; + MISSING_HEADER, + INVALID_URI; @Override public String getKey() { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java index 81be05b..1ca8993 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java @@ -18,9 +18,7 @@ */ package org.apache.olingo.server.core; -import java.util.List; - -import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmBindingTarget; import org.apache.olingo.commons.api.edm.EdmFunctionImport; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.server.api.CustomETagSupport; @@ -28,8 +26,8 @@ import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResourceEntitySet; import org.apache.olingo.server.api.uri.UriResourceFunction; -import org.apache.olingo.server.api.uri.UriResourceKind; import org.apache.olingo.server.api.uri.UriResourceNavigation; +import org.apache.olingo.server.api.uri.UriResourceSingleton; public class PreconditionsValidator { @@ -48,10 +46,10 @@ public class PreconditionsValidator { } public void validatePreconditions(boolean isMediaValue) throws PreconditionRequiredException { - EdmEntitySet affectedEntitySet = extractInformation(); - if (affectedEntitySet != null) { - if ((isMediaValue && customETagSupport.hasMediaETag(affectedEntitySet.getName())) || - (!isMediaValue && customETagSupport.hasETag(affectedEntitySet.getName()))) { + EdmBindingTarget affectedEntitySetOrSingleton = extractInformation(); + if (affectedEntitySetOrSingleton != null) { + if ((isMediaValue && customETagSupport.hasMediaETag(affectedEntitySetOrSingleton)) || + (!isMediaValue && customETagSupport.hasETag(affectedEntitySetOrSingleton))) { checkETagHeaderPresent(); } } @@ -64,75 +62,69 @@ public class PreconditionsValidator { } } - private EdmEntitySet extractInformation() { - EdmEntitySet affectedEntitySet = null; - List<UriResource> uriResourceParts = uriInfo.getUriResourceParts(); - if (uriResourceParts.size() > 0) { - UriResource uriResourcePart = uriResourceParts.get(uriResourceParts.size() - 1); + private EdmBindingTarget extractInformation() throws PreconditionRequiredException { + EdmBindingTarget lastFoundEntitySetOrSingleton = null; + int counter = 0; + for (UriResource uriResourcePart : uriInfo.getUriResourceParts()) { switch (uriResourcePart.getKind()) { + case function: + lastFoundEntitySetOrSingleton = getEnitySetFromFunctionImport(uriResourcePart); + break; + case singleton: + lastFoundEntitySetOrSingleton = ((UriResourceSingleton) uriResourcePart).getSingleton(); + break; case entitySet: - affectedEntitySet = ((UriResourceEntitySet) uriResourcePart).getEntitySet(); + lastFoundEntitySetOrSingleton = getEntitySet(uriResourcePart); break; case navigationProperty: - affectedEntitySet = getEntitySetFromBeginning(); + lastFoundEntitySetOrSingleton = getEntitySetFromNavigation(lastFoundEntitySetOrSingleton, uriResourcePart); break; case value: - affectedEntitySet = getEntitySetOrNavigationEntitySet(uriResourceParts); - break; case action: - affectedEntitySet = getEntitySetOrNavigationEntitySet(uriResourceParts); + // This should not be possible since the URI Parser validates this but to be sure we throw an exception. + if (counter != uriInfo.getUriResourceParts().size() - 1) { + throw new PreconditionRequiredException("$Value or Action must be the last segment in the URI.", + PreconditionRequiredException.MessageKeys.INVALID_URI); + } break; default: - // TODO: Cannot happen but should we throw an exception? + lastFoundEntitySetOrSingleton = null; + break; + } + if (lastFoundEntitySetOrSingleton == null) { + // Once we loose track of the entity set there is no way to retrieve it. break; } - } else { - // TODO: Cannot happen but should we throw an exception? + counter++; } - return affectedEntitySet; + return lastFoundEntitySetOrSingleton; } - private EdmEntitySet getEntitySetOrNavigationEntitySet(List<UriResource> uriResourceParts) { - EdmEntitySet affectedEntitySet = null; - UriResource previousResourcePart = uriResourceParts.get(uriResourceParts.size() - 2); - if (previousResourcePart.getKind() == UriResourceKind.entitySet) { - affectedEntitySet = ((UriResourceEntitySet) previousResourcePart).getEntitySet(); - } else if (previousResourcePart.getKind() == UriResourceKind.navigationProperty) { - affectedEntitySet = getEntitySetFromBeginning(); + private EdmBindingTarget getEnitySetFromFunctionImport(UriResource uriResourcePart) { + UriResourceFunction uriResourceFunction = (UriResourceFunction) uriResourcePart; + EdmFunctionImport functionImport = uriResourceFunction.getFunctionImport(); + if (functionImport != null && functionImport.getReturnedEntitySet() != null + && !uriResourceFunction.isCollection()) { + return functionImport.getReturnedEntitySet(); } - return affectedEntitySet; + return null; } - private EdmEntitySet getEntitySetFromBeginning() { - EdmEntitySet lastFoundES = null; - for (UriResource uriResourcePart : uriInfo.getUriResourceParts()) { - if (UriResourceKind.function == uriResourcePart.getKind()) { - EdmFunctionImport functionImport = ((UriResourceFunction) uriResourcePart).getFunctionImport(); - if (functionImport != null && functionImport.getReturnedEntitySet() != null) { - lastFoundES = functionImport.getReturnedEntitySet(); - } else { - lastFoundES = null; - break; - } - } else if (UriResourceKind.entitySet == uriResourcePart.getKind()) { - lastFoundES = ((UriResourceEntitySet) uriResourcePart).getEntitySet(); - } else if (UriResourceKind.navigationProperty == uriResourcePart.getKind()) { - EdmNavigationProperty navProp = ((UriResourceNavigation) uriResourcePart).getProperty(); - if (lastFoundES != null) { - lastFoundES = (EdmEntitySet) lastFoundES.getRelatedBindingTarget(navProp.getName()); - if (lastFoundES == null) { - break; - } - } - } else if (UriResourceKind.value == uriResourcePart.getKind() - || UriResourceKind.action == uriResourcePart.getKind()) { - // TODO: Should we validate that we are at the end of the resource path - break; - } else { - lastFoundES = null; - break; - } + private EdmBindingTarget getEntitySet(UriResource uriResourcePart) { + UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) uriResourcePart; + if (!uriResourceEntitySet.isCollection()) { + return uriResourceEntitySet.getEntitySet(); + } + return null; + } + + private EdmBindingTarget getEntitySetFromNavigation(EdmBindingTarget lastFoundEntitySetOrSingleton, + UriResource uriResourcePart) { + UriResourceNavigation uriResourceNavigation = (UriResourceNavigation) uriResourcePart; + if (lastFoundEntitySetOrSingleton != null && !uriResourceNavigation.isCollection()) { + EdmNavigationProperty navProp = uriResourceNavigation.getProperty(); + return lastFoundEntitySetOrSingleton.getRelatedBindingTarget(navProp.getName()); } - return lastFoundES; + return null; } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java index 825032d..9011107 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java @@ -18,17 +18,28 @@ */ package org.apache.olingo.server.tecsvc; +import org.apache.olingo.commons.api.edm.EdmBindingTarget; import org.apache.olingo.server.api.CustomETagSupport; public class ETagSupport implements CustomETagSupport { @Override - public boolean hasETag(final String entitySetName) { - return entitySetName.equals("ESCompAllPrim"); + public boolean hasETag(final EdmBindingTarget entitySetOrSingleton) { + return entitySetOrSingleton.getName().equals("ESCompAllPrim"); } @Override - public boolean hasMediaETag(final String entitySetName) { - return entitySetName.equals("ESMedia"); + public boolean hasMediaETag(final EdmBindingTarget entitySetOrSingleton) { + return entitySetOrSingleton.getName().equals("ESMedia"); + } + + @Override + public String getMetadataETag() { + return null; + } + + @Override + public String getServiceDocumentETag() { + return null; } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java index 3dc07c7..033f9af 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java @@ -22,15 +22,23 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmBindingTarget; +import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.commons.core.edm.EdmProviderImpl; import org.apache.olingo.server.api.CustomETagSupport; import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.core.uri.parser.Parser; +import org.apache.olingo.server.core.uri.parser.UriParserException; +import org.apache.olingo.server.core.uri.parser.UriParserSemanticException; +import org.apache.olingo.server.core.uri.validator.UriValidator; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; +import org.junit.Ignore; import org.junit.Test; public class PreconditionsValidatorTest { + // -------------- POSITIVE TESTS -------------------------------------------------------------------------------- + @Test public void simpleEntity() throws Exception { UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)", null, null, getEdm()); @@ -38,16 +46,75 @@ public class PreconditionsValidatorTest { } @Test + public void simpleEntityValue() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport(), uriInfo, "*", "*").validatePreconditions(true); + } + + @Test + public void EntityAndToOneNavigation() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimOne", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport("ESTwoPrim"), uriInfo, "*", "*").validatePreconditions(false); + } + + @Test + public void EntityAndToManyNavigationWithKey() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimMany(1)", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport("ESTwoPrim"), uriInfo, "*", "*").validatePreconditions(false); + } + + @Test + public void EntityAndToOneNavigationValue() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESKeyNav(1)/NavPropertyETMediaOne/$value", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport("ESMedia"), uriInfo, "*", "*").validatePreconditions(true); + } + + @Test public void boundActionOnEsKeyNav() throws Exception { UriInfo uriInfo = new Parser().parseUri("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null, null, getEdm()); - new PreconditionsValidator(new ETagSupport(), uriInfo, "*", "*").validatePreconditions(false); + new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", "*").validatePreconditions(false); } @Test - public void simpleEntityValue() throws Exception { - UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, getEdm()); - new PreconditionsValidator(new ETagSupport(), uriInfo, "*", "*").validatePreconditions(true); + public void boundActionOnEsKeyNavWithNavigation() throws Exception { + UriInfo uriInfo = + new Parser().parseUri("ESKeyNav(1)/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null, + null, getEdm()); + new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", "*").validatePreconditions(false); + } + + @Test + public void singleton() throws Exception { + UriInfo uriInfo = new Parser().parseUri("SI", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport("SI"), uriInfo, "*", "*").validatePreconditions(false); + } + + @Test + public void singletonWithNavigation() throws Exception { + UriInfo uriInfo = new Parser().parseUri("SINav/NavPropertyETKeyNavOne", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", "*").validatePreconditions(false); + } + + @Test + public void singletonWithNavigationValue() throws Exception { + UriInfo uriInfo = + new Parser().parseUri("SINav/NavPropertyETKeyNavOne/NavPropertyETMediaOne/$value", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport("ESMedia"), uriInfo, "*", "*").validatePreconditions(false); + } + + @Test + public void singletonWithAction() throws Exception { + UriInfo uriInfo = new Parser().parseUri("SINav/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport("SINav"), uriInfo, "*", "*").validatePreconditions(false); + } + + @Test + public void singletonWithActionAndNavigation() throws Exception { + UriInfo uriInfo = + new Parser().parseUri("SINav/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null, null, + getEdm()); + new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", "*").validatePreconditions(false); } @Test @@ -56,51 +123,99 @@ public class PreconditionsValidatorTest { new PreconditionsValidator(new ETagSupport(true, false), uriInfo, null, null).validatePreconditions(true); } + // -------------- IGNORE VALIDATION TESTS ----------------------------------------------------------------------- + @Test - public void EntityAndToOneNavigation() throws Exception { - UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimOne", null, null, getEdm()); - new PreconditionsValidator(new ETagSupport("ESTwoPrim"), uriInfo, "*", "*").validatePreconditions(false); + public void entitySetMustNotLeadToException() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESAllPrim", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(false); } @Test - public void simpleEntityPreconditionsReqException() throws Exception { - UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)", null, null, getEdm()); - try { - new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(false); - fail("Expected a PreconditionRequiredException but was not thrown"); - } catch (PreconditionRequiredException e) { - assertEquals(PreconditionRequiredException.MessageKeys.MISSING_HEADER, e.getMessageKey()); - } + public void propertyMustNotLeadToException() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/PropertyInt16", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(false); + } + + @Test + public void propertyValueMustNotLeadToException() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/PropertyInt16/$value", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(true); + } + + @Test + public void navigationToManyMustNotLeadToException() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimMany", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(false); } @Test - public void boundActionOnEsKeyNavPreconditionsRequired() throws Exception { + public void navigationOnPropertyMustNotLeadToException() throws Exception { + UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimOne/PropertyInt16", null, null, getEdm()); + new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(false); + } + + @Test + public void navigationToManyOnActionMustNotLeadToException() throws Exception { UriInfo uriInfo = - new Parser().parseUri("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null, null, getEdm()); - try { - new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, null, null).validatePreconditions(false); - fail("Expected a PreconditionRequiredException but was not thrown"); - } catch (PreconditionRequiredException e) { - assertEquals(PreconditionRequiredException.MessageKeys.MISSING_HEADER, e.getMessageKey()); - } + new Parser().parseUri("ESTwoPrim(1)/NavPropertyETAllPrimMany/Namespace1_Alias.BAESAllPrimRTETAllPrim", null, + null, getEdm()); + new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(false); } @Test - public void simpleEntityValuePreconditionsRequired() throws Exception { - UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, getEdm()); - try { - new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(true); - fail("Expected a PreconditionRequiredException but was not thrown"); - } catch (PreconditionRequiredException e) { - assertEquals(PreconditionRequiredException.MessageKeys.MISSING_HEADER, e.getMessageKey()); - } + public void navigationWithoutBindingMustNotLeadToAnException() throws Exception { + UriInfo uriInfo = + new Parser() + .parseUri( + "ESTwoBaseTwoKeyNav(PropertyInt16=1,PropertyString='test')" + + "/NavPropertyETBaseTwoKeyNavMany(PropertyInt16=1,PropertyString='test')", + null, null, getEdm()); + new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(false); } + // -------------- NEGATIVE TESTS -------------------------------------------------------------------------------- + @Test - public void EntityAndToOneNavigationPreconditionsRequired() throws Exception { - UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimOne", null, null, getEdm()); + public void positiveTestsMustLeadToAnExceptionIfNoHeaderIsPresent() throws Exception { + runException("ESAllPrim(1)", null); + runException("ESMedia(1)/$value", null); + runException("ESAllPrim(1)/NavPropertyETTwoPrimOne", null); + runException("ESAllPrim(1)/NavPropertyETTwoPrimMany(1)", null); + runException("ESKeyNav(1)/NavPropertyETMediaOne/$value", null); + runException("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null); + runException("ESKeyNav(1)/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null); + + runException("SI", null); + runException("SINav/NavPropertyETKeyNavOne", null); + runException("SINav/NavPropertyETKeyNavOne/NavPropertyETMediaOne/$value", null); + runException("SINav/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null); + runException("SINav/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null); + } + + @Ignore + @Test + public void resourceSegmentAfterActionMustLeadToUriParserException() throws Exception { + //TODO: Check with URI Parser + UriInfo uriInfo = + new Parser().parseUri("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav/PropertyInt16", null, null, + getEdm()); + new UriValidator().validate(uriInfo, HttpMethod.GET); + new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", "*").validatePreconditions(false); + } + + @Test(expected = UriParserSemanticException.class) + public void valueMustBeLastSegment() throws Exception { + new Parser().parseUri("ESMedia(1)/$value/PropertyInt16", null, null, getEdm()); + } + + private void runException(String uri, String expectedEntitySet) throws UriParserException { + UriInfo uriInfo = new Parser().parseUri(uri, null, null, getEdm()); try { - new PreconditionsValidator(new ETagSupport(), uriInfo, null, null).validatePreconditions(false); + CustomETagSupport etagSupport = + expectedEntitySet == null ? new ETagSupport() : new ETagSupport(expectedEntitySet); + boolean isMedia = uri.endsWith("$value"); + new PreconditionsValidator(etagSupport, uriInfo, null, null).validatePreconditions(isMedia); fail("Expected a PreconditionRequiredException but was not thrown"); } catch (PreconditionRequiredException e) { assertEquals(PreconditionRequiredException.MessageKeys.MISSING_HEADER, e.getMessageKey()); @@ -117,33 +232,41 @@ public class PreconditionsValidatorTest { private boolean mediaETag = true; private String entitySetName; - public ETagSupport() { - } + public ETagSupport() {} public ETagSupport(String entitySetName) { this.entitySetName = entitySetName; - } + } public ETagSupport(boolean eTag, boolean mediaETag) { this.eTag = eTag; this.mediaETag = mediaETag; } - @Override - public boolean hasETag(String entitySetName) { - if(this.entitySetName != null){ - assertEquals(this.entitySetName, entitySetName); + public boolean hasETag(EdmBindingTarget entitySetOrSingeton) { + if (this.entitySetName != null) { + assertEquals(this.entitySetName, entitySetOrSingeton.getName()); } return eTag; } @Override - public boolean hasMediaETag(String entitySetName) { - if(this.entitySetName != null){ - assertEquals(this.entitySetName, entitySetName); + public boolean hasMediaETag(EdmBindingTarget entitySetOrSingelton) { + if (this.entitySetName != null) { + assertEquals(this.entitySetName, entitySetOrSingelton.getName()); } return mediaETag; } + + @Override + public String getMetadataETag() { + return null; + } + + @Override + public String getServiceDocumentETag() { + return null; + } } }
