mirror of
https://github.com/apache/olingo-odata4.git
synced 2025-03-06 08:39:14 +00:00
[OLINGO-663] helper for conditional handling
Change-Id: I48599dc609bfb53bc2903083abe235458109e20a Signed-off-by: Christian Amend <christian.amend@sap.com>
This commit is contained in:
parent
b8187f5307
commit
1f286fd424
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.apache.olingo.server.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.olingo.commons.api.ODataRuntimeException;
|
||||
@ -30,6 +29,7 @@ import org.apache.olingo.server.api.deserializer.DeserializerException;
|
||||
import org.apache.olingo.server.api.deserializer.FixedFormatDeserializer;
|
||||
import org.apache.olingo.server.api.deserializer.ODataDeserializer;
|
||||
import org.apache.olingo.server.api.edmx.EdmxReference;
|
||||
import org.apache.olingo.server.api.etag.ETagHelper;
|
||||
import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
|
||||
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
||||
import org.apache.olingo.server.api.serializer.SerializerException;
|
||||
@ -118,11 +118,8 @@ public abstract class OData {
|
||||
public abstract EdmPrimitiveType createPrimitiveTypeInstance(EdmPrimitiveTypeKind kind);
|
||||
|
||||
/**
|
||||
* Creates ETag information from the values of a HTTP header
|
||||
* containing a list of entity tags or a single star character, i.e.,
|
||||
* <code>If-Match</code> and <code>If-None-Match</code>.
|
||||
* @param values the collection of header values
|
||||
* @return an {@link ETagInformation} instance
|
||||
* Creates a new ETag helper object for performing ETag-related tasks.
|
||||
* It can be used in Processor implementations.
|
||||
*/
|
||||
public abstract ETagInformation createETagInformation(final Collection<String> values);
|
||||
public abstract ETagHelper createETagHelper();
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ package org.apache.olingo.server.api;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.olingo.server.api.etag.CustomETagSupport;
|
||||
import org.apache.olingo.server.api.processor.Processor;
|
||||
import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.olingo.server.api;
|
||||
package org.apache.olingo.server.api.etag;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.server.api.etag;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Used for ETag-related tasks.
|
||||
*/
|
||||
public interface ETagHelper {
|
||||
/**
|
||||
* <p>Checks the preconditions of a read request with a given ETag value
|
||||
* against the If-Match and If-None-Match HTTP headers.</p>
|
||||
* <p>If the given ETag value is not matched by the ETag information in the If-Match headers,
|
||||
* and there are ETags in the headers to be matched, a "Precondition Failed" exception is
|
||||
* thrown.</p>
|
||||
* <p>If the given ETag value is matched by the ETag information in the If-None-Match headers,
|
||||
* <code>true</code> is returned, and applications are supposed to return an empty response
|
||||
* with a "Not Modified" status code and the ETag header, <code>false</code> otherwise.</p>
|
||||
* <p>All matching uses weak comparison as described in
|
||||
* <a href="https://www.ietf.org/rfc/rfc7232.txt">RFC 7232</a>, section 2.3.2.</p>
|
||||
* <p>This method does not nothing and returns <code>false</code> if the ETag value is
|
||||
* <code>null</code>.</p>
|
||||
* @param eTag the ETag value to match
|
||||
* @param ifMatchHeaders the If-Match header values
|
||||
* @param ifNoneMatchHeaders the If-None-Match header values
|
||||
* @return whether a "Not Modified" response should be used
|
||||
*/
|
||||
public boolean checkReadPreconditions(String eTag,
|
||||
Collection<String> ifMatchHeaders, Collection<String> ifNoneMatchHeaders)
|
||||
throws PreconditionRequiredException;
|
||||
|
||||
/**
|
||||
* <p>Checks the preconditions of a change request (with HTTP methods PUT, PATCH, or DELETE)
|
||||
* with a given ETag value against the If-Match and If-None-Match HTTP headers.</p>
|
||||
* <p>If the given ETag value is not matched by the ETag information in the If-Match headers,
|
||||
* and there are ETags in the headers to be matched, or
|
||||
* if the given ETag value is matched by the ETag information in the If-None-Match headers,
|
||||
* a "Precondition Failed" exception is thrown.</p>
|
||||
* <p>All matching uses weak comparison as described in
|
||||
* <a href="https://www.ietf.org/rfc/rfc7232.txt">RFC 7232</a>, section 2.3.2.</p>
|
||||
* <p>This method does not nothing if the ETag value is <code>null</code>.</p>
|
||||
* @param eTag the ETag value to match
|
||||
* @param ifMatchHeaders the If-Match header values
|
||||
* @param ifNoneMatchHeaders the If-None-Match header values
|
||||
*/
|
||||
public void checkChangePreconditions(String eTag,
|
||||
Collection<String> ifMatchHeaders, Collection<String> ifNoneMatchHeaders)
|
||||
throws PreconditionRequiredException;
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.olingo.server.core;
|
||||
package org.apache.olingo.server.api.etag;
|
||||
|
||||
import org.apache.olingo.server.api.ODataLibraryException;
|
||||
|
||||
@ -25,7 +25,9 @@ public class PreconditionRequiredException extends ODataLibraryException {
|
||||
|
||||
public static enum MessageKeys implements MessageKey {
|
||||
/** no parameter */
|
||||
MISSING_HEADER,
|
||||
MISSING_HEADER,
|
||||
/** no parameter */
|
||||
FAILED,
|
||||
/** no parameter */
|
||||
INVALID_URI;
|
||||
|
@ -33,6 +33,7 @@ import org.apache.olingo.server.api.ODataApplicationException;
|
||||
import org.apache.olingo.server.api.ODataLibraryException;
|
||||
import org.apache.olingo.server.api.ODataRequest;
|
||||
import org.apache.olingo.server.api.ODataResponse;
|
||||
import org.apache.olingo.server.api.etag.PreconditionRequiredException;
|
||||
import org.apache.olingo.server.api.processor.ActionComplexCollectionProcessor;
|
||||
import org.apache.olingo.server.api.processor.ActionComplexProcessor;
|
||||
import org.apache.olingo.server.api.processor.ActionEntityCollectionProcessor;
|
||||
@ -67,6 +68,7 @@ import org.apache.olingo.server.api.uri.UriResourcePartTyped;
|
||||
import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
|
||||
import org.apache.olingo.server.api.uri.UriResourceProperty;
|
||||
import org.apache.olingo.server.core.batchhandler.BatchHandler;
|
||||
import org.apache.olingo.server.core.etag.PreconditionsValidator;
|
||||
|
||||
public class ODataDispatcher {
|
||||
|
||||
|
@ -26,6 +26,7 @@ import org.apache.olingo.server.api.ODataApplicationException;
|
||||
import org.apache.olingo.server.api.ODataLibraryException;
|
||||
import org.apache.olingo.server.api.ODataLibraryException.ODataErrorMessage;
|
||||
import org.apache.olingo.server.api.deserializer.DeserializerException;
|
||||
import org.apache.olingo.server.api.etag.PreconditionRequiredException;
|
||||
import org.apache.olingo.server.api.serializer.SerializerException;
|
||||
import org.apache.olingo.server.core.uri.parser.UriParserException;
|
||||
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
|
||||
|
@ -26,7 +26,6 @@ import org.apache.olingo.commons.api.format.ContentType;
|
||||
import org.apache.olingo.commons.api.format.ODataFormat;
|
||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||
import org.apache.olingo.commons.api.http.HttpMethod;
|
||||
import org.apache.olingo.server.api.CustomETagSupport;
|
||||
import org.apache.olingo.server.api.OData;
|
||||
import org.apache.olingo.server.api.ODataApplicationException;
|
||||
import org.apache.olingo.server.api.ODataLibraryException;
|
||||
@ -35,6 +34,8 @@ import org.apache.olingo.server.api.ODataResponse;
|
||||
import org.apache.olingo.server.api.ODataServerError;
|
||||
import org.apache.olingo.server.api.ServiceMetadata;
|
||||
import org.apache.olingo.server.api.deserializer.DeserializerException;
|
||||
import org.apache.olingo.server.api.etag.CustomETagSupport;
|
||||
import org.apache.olingo.server.api.etag.PreconditionRequiredException;
|
||||
import org.apache.olingo.server.api.processor.DefaultProcessor;
|
||||
import org.apache.olingo.server.api.processor.ErrorProcessor;
|
||||
import org.apache.olingo.server.api.processor.Processor;
|
||||
|
@ -33,7 +33,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.olingo.commons.api.ODataRuntimeException;
|
||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||
import org.apache.olingo.commons.api.http.HttpMethod;
|
||||
import org.apache.olingo.server.api.CustomETagSupport;
|
||||
import org.apache.olingo.server.api.ODataServerError;
|
||||
import org.apache.olingo.server.api.OData;
|
||||
import org.apache.olingo.server.api.ODataHttpHandler;
|
||||
@ -41,6 +40,7 @@ import org.apache.olingo.server.api.ODataRequest;
|
||||
import org.apache.olingo.server.api.ODataResponse;
|
||||
import org.apache.olingo.server.api.ODataLibraryException;
|
||||
import org.apache.olingo.server.api.ServiceMetadata;
|
||||
import org.apache.olingo.server.api.etag.CustomETagSupport;
|
||||
import org.apache.olingo.server.api.processor.Processor;
|
||||
import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
|
||||
import org.apache.olingo.server.api.serializer.SerializerException;
|
||||
|
@ -18,8 +18,6 @@
|
||||
*/
|
||||
package org.apache.olingo.server.core;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
|
||||
@ -27,7 +25,6 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
|
||||
import org.apache.olingo.commons.api.format.ODataFormat;
|
||||
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
|
||||
import org.apache.olingo.server.api.ETagInformation;
|
||||
import org.apache.olingo.server.api.OData;
|
||||
import org.apache.olingo.server.api.ODataHttpHandler;
|
||||
import org.apache.olingo.server.api.ServiceMetadata;
|
||||
@ -35,12 +32,14 @@ import org.apache.olingo.server.api.deserializer.DeserializerException;
|
||||
import org.apache.olingo.server.api.deserializer.FixedFormatDeserializer;
|
||||
import org.apache.olingo.server.api.deserializer.ODataDeserializer;
|
||||
import org.apache.olingo.server.api.edmx.EdmxReference;
|
||||
import org.apache.olingo.server.api.etag.ETagHelper;
|
||||
import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
|
||||
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
||||
import org.apache.olingo.server.api.serializer.SerializerException;
|
||||
import org.apache.olingo.server.api.uri.UriHelper;
|
||||
import org.apache.olingo.server.core.deserializer.FixedFormatDeserializerImpl;
|
||||
import org.apache.olingo.server.core.deserializer.json.ODataJsonDeserializer;
|
||||
import org.apache.olingo.server.core.etag.ETagHelperImpl;
|
||||
import org.apache.olingo.server.core.serializer.FixedFormatSerializerImpl;
|
||||
import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer;
|
||||
import org.apache.olingo.server.core.serializer.xml.ODataXmlSerializerImpl;
|
||||
@ -96,21 +95,20 @@ public class ODataImpl extends OData {
|
||||
|
||||
@Override
|
||||
public ODataDeserializer createDeserializer(final ODataFormat format) throws DeserializerException {
|
||||
ODataDeserializer serializer;
|
||||
ODataDeserializer deserializer;
|
||||
switch (format) {
|
||||
case JSON:
|
||||
case JSON_NO_METADATA:
|
||||
case JSON_FULL_METADATA:
|
||||
serializer = new ODataJsonDeserializer();
|
||||
deserializer = new ODataJsonDeserializer();
|
||||
break;
|
||||
case XML:
|
||||
// We do not support xml deserialization right now so this mus lead to an error
|
||||
// We do not support XML deserialization right now so this must lead to an error.
|
||||
default:
|
||||
throw new DeserializerException("Unsupported format: " + format,
|
||||
SerializerException.MessageKeys.UNSUPPORTED_FORMAT, format.toString());
|
||||
DeserializerException.MessageKeys.UNSUPPORTED_FORMAT, format.toString());
|
||||
}
|
||||
|
||||
return serializer;
|
||||
return deserializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -119,10 +117,7 @@ public class ODataImpl extends OData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ETagInformation createETagInformation(final Collection<String> values) {
|
||||
final Collection<String> eTags = ETagParser.parse(values);
|
||||
final boolean isAll = eTags.size() == 1 && eTags.iterator().next().equals("*");
|
||||
return new ETagInformation(isAll,
|
||||
isAll ? Collections.<String> emptySet() : Collections.unmodifiableCollection(eTags));
|
||||
public ETagHelper createETagHelper() {
|
||||
return new ETagHelperImpl();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.server.core.etag;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.olingo.server.api.etag.ETagHelper;
|
||||
import org.apache.olingo.server.api.etag.PreconditionRequiredException;
|
||||
|
||||
public class ETagHelperImpl implements ETagHelper {
|
||||
|
||||
@Override
|
||||
public boolean checkReadPreconditions(final String eTag,
|
||||
final Collection<String> ifMatchHeaders, final Collection<String> ifNoneMatchHeaders)
|
||||
throws PreconditionRequiredException {
|
||||
if (eTag != null) {
|
||||
final ETagInformation ifMatch = createETagInformation(ifMatchHeaders);
|
||||
if (!ifMatch.isMatchedBy(eTag) && !ifMatch.getETags().isEmpty()) {
|
||||
throw new PreconditionRequiredException("The If-Match precondition is not fulfilled.",
|
||||
PreconditionRequiredException.MessageKeys.FAILED);
|
||||
}
|
||||
return createETagInformation(ifNoneMatchHeaders).isMatchedBy(eTag);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkChangePreconditions(final String eTag,
|
||||
final Collection<String> ifMatchHeaders, final Collection<String> ifNoneMatchHeaders)
|
||||
throws PreconditionRequiredException {
|
||||
if (eTag != null) {
|
||||
final ETagInformation ifMatch = createETagInformation(ifMatchHeaders);
|
||||
final ETagInformation ifNoneMatch = createETagInformation(ifNoneMatchHeaders);
|
||||
if (!ifMatch.isMatchedBy(eTag) && !ifMatch.getETags().isEmpty()
|
||||
|| ifNoneMatch.isMatchedBy(eTag)) {
|
||||
throw new PreconditionRequiredException("The preconditions are not fulfilled.",
|
||||
PreconditionRequiredException.MessageKeys.FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates ETag information from the values of a HTTP header
|
||||
* containing a list of entity tags or a single star character, i.e.,
|
||||
* <code>If-Match</code> and <code>If-None-Match</code>.
|
||||
* @param values the collection of header values
|
||||
* @return an {@link ETagInformation} instance
|
||||
*/
|
||||
protected ETagInformation createETagInformation(final Collection<String> values) {
|
||||
final Collection<String> eTags = ETagParser.parse(values);
|
||||
final boolean isAll = eTags.size() == 1 && eTags.iterator().next().equals("*");
|
||||
return new ETagInformation(isAll,
|
||||
isAll ? Collections.<String> emptySet() : Collections.unmodifiableCollection(eTags));
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.olingo.server.api;
|
||||
package org.apache.olingo.server.core.etag;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.olingo.server.core;
|
||||
package org.apache.olingo.server.core.etag;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
@ -16,12 +16,13 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.olingo.server.core;
|
||||
package org.apache.olingo.server.core.etag;
|
||||
|
||||
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;
|
||||
import org.apache.olingo.server.api.etag.CustomETagSupport;
|
||||
import org.apache.olingo.server.api.etag.PreconditionRequiredException;
|
||||
import org.apache.olingo.server.api.uri.UriInfo;
|
||||
import org.apache.olingo.server.api.uri.UriResource;
|
||||
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
|
@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.olingo.server.core;
|
||||
package org.apache.olingo.server.core.etag;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.hasItems;
|
||||
@ -28,17 +28,15 @@ import static org.junit.Assert.assertTrue;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.olingo.server.api.ETagInformation;
|
||||
import org.apache.olingo.server.api.OData;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ETagParserTest {
|
||||
|
||||
private static final OData odata = OData.newInstance();
|
||||
private static final ETagHelperImpl eTagHelper = new ETagHelperImpl();
|
||||
|
||||
@Test
|
||||
public void empty() {
|
||||
final ETagInformation eTagInformation = odata.createETagInformation(null);
|
||||
final ETagInformation eTagInformation = eTagHelper.createETagInformation(null);
|
||||
assertFalse(eTagInformation.isAll());
|
||||
assertNotNull(eTagInformation.getETags());
|
||||
assertTrue(eTagInformation.getETags().isEmpty());
|
||||
@ -46,7 +44,7 @@ public class ETagParserTest {
|
||||
|
||||
@Test
|
||||
public void loneStar() {
|
||||
final ETagInformation eTagInformation = odata.createETagInformation(Collections.singleton("*"));
|
||||
final ETagInformation eTagInformation = eTagHelper.createETagInformation(Collections.singleton("*"));
|
||||
assertTrue(eTagInformation.isAll());
|
||||
assertNotNull(eTagInformation.getETags());
|
||||
assertTrue(eTagInformation.getETags().isEmpty());
|
||||
@ -54,7 +52,7 @@ public class ETagParserTest {
|
||||
|
||||
@Test
|
||||
public void starWins() {
|
||||
final ETagInformation eTagInformation = odata.createETagInformation(Arrays.asList("\"ETag\"", "*"));
|
||||
final ETagInformation eTagInformation = eTagHelper.createETagInformation(Arrays.asList("\"ETag\"", "*"));
|
||||
assertTrue(eTagInformation.isAll());
|
||||
assertNotNull(eTagInformation.getETags());
|
||||
assertTrue(eTagInformation.getETags().isEmpty());
|
||||
@ -62,7 +60,7 @@ public class ETagParserTest {
|
||||
|
||||
@Test
|
||||
public void starAsEtagAndEmptyEtag() {
|
||||
final ETagInformation eTagInformation = odata.createETagInformation(
|
||||
final ETagInformation eTagInformation = eTagHelper.createETagInformation(
|
||||
Collections.singleton("\"*\", \"\""));
|
||||
assertFalse(eTagInformation.isAll());
|
||||
assertNotNull(eTagInformation.getETags());
|
||||
@ -72,7 +70,7 @@ public class ETagParserTest {
|
||||
|
||||
@Test
|
||||
public void severalEtags() {
|
||||
final ETagInformation eTagInformation = odata.createETagInformation(
|
||||
final ETagInformation eTagInformation = eTagHelper.createETagInformation(
|
||||
Arrays.asList("\"ETag1\"", "\"ETag2\",, , ,W/\"ETag3\", ,"));
|
||||
assertFalse(eTagInformation.isAll());
|
||||
assertNotNull(eTagInformation.getETags());
|
||||
@ -82,7 +80,7 @@ public class ETagParserTest {
|
||||
|
||||
@Test
|
||||
public void duplicateEtagValues() {
|
||||
final ETagInformation eTagInformation = odata.createETagInformation(
|
||||
final ETagInformation eTagInformation = eTagHelper.createETagInformation(
|
||||
Arrays.asList("\"ETag1\"", "\"ETag2\", W/\"ETag1\", \"ETag1\""));
|
||||
assertFalse(eTagInformation.isAll());
|
||||
assertNotNull(eTagInformation.getETags());
|
||||
@ -92,7 +90,7 @@ public class ETagParserTest {
|
||||
|
||||
@Test
|
||||
public void specialCharacters() {
|
||||
final ETagInformation eTagInformation = odata.createETagInformation(
|
||||
final ETagInformation eTagInformation = eTagHelper.createETagInformation(
|
||||
Collections.singleton("\"!#$%&'()*+,-./:;<=>?@[]^_`{|}~¡\u00FF\", \"ETag2\""));
|
||||
assertFalse(eTagInformation.isAll());
|
||||
assertNotNull(eTagInformation.getETags());
|
||||
@ -103,7 +101,7 @@ public class ETagParserTest {
|
||||
|
||||
@Test
|
||||
public void wrongFormat() {
|
||||
final ETagInformation eTagInformation = odata.createETagInformation(
|
||||
final ETagInformation eTagInformation = eTagHelper.createETagInformation(
|
||||
Arrays.asList("\"ETag1\", ETag2", "w/\"ETag3\"", "W//\"ETag4\"", "W/ETag5",
|
||||
"\"\"ETag6\"\"", " \"ETag7\"\"ETag7\" ", "\"ETag8\" \"ETag8\"",
|
||||
"\"ETag 9\"", "\"ETag10\""));
|
||||
@ -115,17 +113,17 @@ public class ETagParserTest {
|
||||
|
||||
@Test
|
||||
public void match() {
|
||||
assertFalse(odata.createETagInformation(Collections.<String> emptySet()).isMatchedBy("\"ETag\""));
|
||||
assertFalse(odata.createETagInformation(Collections.singleton("\"ETag\"")).isMatchedBy(null));
|
||||
assertTrue(odata.createETagInformation(Collections.singleton("\"ETag\"")).isMatchedBy("\"ETag\""));
|
||||
assertTrue(odata.createETagInformation(Collections.singleton("*")).isMatchedBy("\"ETag\""));
|
||||
assertTrue(odata.createETagInformation(Collections.singleton("\"ETag\"")).isMatchedBy("W/\"ETag\""));
|
||||
assertTrue(odata.createETagInformation(Collections.singleton("W/\"ETag\"")).isMatchedBy("\"ETag\""));
|
||||
assertFalse(odata.createETagInformation(Collections.singleton("\"ETag\"")).isMatchedBy("W/\"ETag2\""));
|
||||
assertFalse(odata.createETagInformation(Collections.singleton("W/\"ETag\"")).isMatchedBy("\"ETag2\""));
|
||||
assertTrue(odata.createETagInformation(Arrays.asList("\"ETag1\",\"ETag2\"", "\"ETag3\",\"ETag4\""))
|
||||
assertFalse(eTagHelper.createETagInformation(Collections.<String> emptySet()).isMatchedBy("\"ETag\""));
|
||||
assertFalse(eTagHelper.createETagInformation(Collections.singleton("\"ETag\"")).isMatchedBy(null));
|
||||
assertTrue(eTagHelper.createETagInformation(Collections.singleton("\"ETag\"")).isMatchedBy("\"ETag\""));
|
||||
assertTrue(eTagHelper.createETagInformation(Collections.singleton("*")).isMatchedBy("\"ETag\""));
|
||||
assertTrue(eTagHelper.createETagInformation(Collections.singleton("\"ETag\"")).isMatchedBy("W/\"ETag\""));
|
||||
assertTrue(eTagHelper.createETagInformation(Collections.singleton("W/\"ETag\"")).isMatchedBy("\"ETag\""));
|
||||
assertFalse(eTagHelper.createETagInformation(Collections.singleton("\"ETag\"")).isMatchedBy("W/\"ETag2\""));
|
||||
assertFalse(eTagHelper.createETagInformation(Collections.singleton("W/\"ETag\"")).isMatchedBy("\"ETag2\""));
|
||||
assertTrue(eTagHelper.createETagInformation(Arrays.asList("\"ETag1\",\"ETag2\"", "\"ETag3\",\"ETag4\""))
|
||||
.isMatchedBy("\"ETag4\""));
|
||||
assertFalse(odata.createETagInformation(Arrays.asList("\"ETag1\",\"ETag2\"", "\"ETag3\",\"ETag4\""))
|
||||
assertFalse(eTagHelper.createETagInformation(Arrays.asList("\"ETag1\",\"ETag2\"", "\"ETag3\",\"ETag4\""))
|
||||
.isMatchedBy("\"ETag5\""));
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
package org.apache.olingo.server.tecsvc;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
|
||||
import org.apache.olingo.server.api.CustomETagSupport;
|
||||
import org.apache.olingo.server.api.etag.CustomETagSupport;
|
||||
|
||||
public class ETagSupport implements CustomETagSupport {
|
||||
|
||||
|
@ -161,9 +161,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
||||
.validate(edmEntitySet, deserializerResult.getEntity());
|
||||
|
||||
entity = dataProvider.create(edmEntitySet);
|
||||
dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, deserializerResult.getEntity(), false,
|
||||
|
||||
true);
|
||||
dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, deserializerResult.getEntity(), false, true);
|
||||
expand = deserializerResult.getExpandTree();
|
||||
}
|
||||
|
||||
@ -199,7 +197,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
||||
}
|
||||
}
|
||||
|
||||
checkChangePreconditions(entity.getETag(),
|
||||
odata.createETagHelper().checkChangePreconditions(entity.getETag(),
|
||||
request.getHeaders(HttpHeader.IF_MATCH),
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH));
|
||||
checkRequestFormat(requestFormat);
|
||||
@ -232,7 +230,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
||||
final EdmEntityType edmEntityType = edmEntitySet.getEntityType();
|
||||
|
||||
Entity entity = readEntity(uriInfo);
|
||||
checkChangePreconditions(entity.getMediaETag(),
|
||||
odata.createETagHelper().checkChangePreconditions(entity.getMediaETag(),
|
||||
request.getHeaders(HttpHeader.IF_MATCH),
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH));
|
||||
checkRequestFormat(requestFormat);
|
||||
@ -251,13 +249,13 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
||||
|
||||
@Override
|
||||
public void deleteEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
|
||||
throws ODataApplicationException {
|
||||
throws ODataLibraryException, ODataApplicationException {
|
||||
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo);
|
||||
final Entity entity = readEntity(uriInfo);
|
||||
final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
|
||||
final boolean isValue = resourcePaths.get(resourcePaths.size() - 1) instanceof UriResourceValue;
|
||||
|
||||
checkChangePreconditions(isValue ? entity.getMediaETag() : entity.getETag(),
|
||||
odata.createETagHelper().checkChangePreconditions(isValue ? entity.getMediaETag() : entity.getETag(),
|
||||
request.getHeaders(HttpHeader.IF_MATCH),
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH));
|
||||
dataProvider.delete(edmEntitySet, entity);
|
||||
@ -353,9 +351,13 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
||||
|
||||
final Entity entity = readEntity(uriInfo);
|
||||
|
||||
checkReadPreconditions(entity.getETag(),
|
||||
if (odata.createETagHelper().checkReadPreconditions(entity.getETag(),
|
||||
request.getHeaders(HttpHeader.IF_MATCH),
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH));
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH))) {
|
||||
response.setStatusCode(HttpStatusCode.NOT_MODIFIED.getStatusCode());
|
||||
response.setHeader(HttpHeader.ETAG, entity.getETag());
|
||||
return;
|
||||
}
|
||||
|
||||
final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
|
||||
final ExpandOption expand = uriInfo.getExpandOption();
|
||||
|
@ -171,9 +171,13 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
|
||||
final Entity entity = readEntity(uriInfo);
|
||||
|
||||
if (entity != null && entity.getETag() != null) {
|
||||
checkReadPreconditions(entity.getETag(),
|
||||
if (odata.createETagHelper().checkReadPreconditions(entity.getETag(),
|
||||
request.getHeaders(HttpHeader.IF_MATCH),
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH));
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH))) {
|
||||
response.setStatusCode(HttpStatusCode.NOT_MODIFIED.getStatusCode());
|
||||
response.setHeader(HttpHeader.ETAG, entity.getETag());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final Property property = entity == null ?
|
||||
@ -219,7 +223,7 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
|
||||
final EdmEntitySet edmEntitySet = getEdmEntitySet(resource);
|
||||
|
||||
Entity entity = readEntity(uriInfo);
|
||||
checkChangePreconditions(entity.getETag(),
|
||||
odata.createETagHelper().checkChangePreconditions(entity.getETag(),
|
||||
request.getHeaders(HttpHeader.IF_MATCH),
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH));
|
||||
|
||||
@ -252,13 +256,13 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
|
||||
}
|
||||
|
||||
private void deleteProperty(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
|
||||
throws ODataApplicationException {
|
||||
throws ODataLibraryException, ODataApplicationException {
|
||||
final UriInfoResource resource = uriInfo.asUriInfoResource();
|
||||
validatePath(resource);
|
||||
getEdmEntitySet(uriInfo); // including checks
|
||||
|
||||
Entity entity = readEntity(uriInfo);
|
||||
checkChangePreconditions(entity.getETag(),
|
||||
odata.createETagHelper().checkChangePreconditions(entity.getETag(),
|
||||
request.getHeaders(HttpHeader.IF_MATCH),
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH));
|
||||
|
||||
@ -397,9 +401,13 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
|
||||
|
||||
final Entity entity = readEntity(uriInfo);
|
||||
if (entity != null && entity.getETag() != null) {
|
||||
checkReadPreconditions(entity.getETag(),
|
||||
if (odata.createETagHelper().checkReadPreconditions(entity.getETag(),
|
||||
request.getHeaders(HttpHeader.IF_MATCH),
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH));
|
||||
request.getHeaders(HttpHeader.IF_NONE_MATCH))) {
|
||||
response.setStatusCode(HttpStatusCode.NOT_MODIFIED.getStatusCode());
|
||||
response.setHeader(HttpHeader.ETAG, entity.getETag());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final Property property = entity == null ?
|
||||
|
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.apache.olingo.server.tecsvc.processor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@ -32,7 +31,6 @@ import org.apache.olingo.commons.api.edm.EdmFunction;
|
||||
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
|
||||
import org.apache.olingo.commons.api.format.ContentType;
|
||||
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||
import org.apache.olingo.server.api.ETagInformation;
|
||||
import org.apache.olingo.server.api.OData;
|
||||
import org.apache.olingo.server.api.ODataApplicationException;
|
||||
import org.apache.olingo.server.api.ServiceMetadata;
|
||||
@ -257,34 +255,4 @@ public abstract class TechnicalProcessor implements Processor {
|
||||
HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkReadPreconditions(final String eTag,
|
||||
final Collection<String> ifMatchHeaders, final Collection<String> ifNoneMatchHeaders)
|
||||
throws ODataApplicationException {
|
||||
if (eTag != null) {
|
||||
final ETagInformation ifMatch = odata.createETagInformation(ifMatchHeaders);
|
||||
if (!ifMatch.isMatchedBy(eTag) && !ifMatch.getETags().isEmpty()) {
|
||||
throw new ODataApplicationException("The If-Match precondition is not fulfilled.",
|
||||
HttpStatusCode.PRECONDITION_FAILED.getStatusCode(), Locale.ROOT);
|
||||
}
|
||||
if (odata.createETagInformation(ifNoneMatchHeaders).isMatchedBy(eTag)) {
|
||||
throw new ODataApplicationException("The entity has not been modified.",
|
||||
HttpStatusCode.NOT_MODIFIED.getStatusCode(), Locale.ROOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkChangePreconditions(final String eTag,
|
||||
final Collection<String> ifMatchHeaders, final Collection<String> ifNoneMatchHeaders)
|
||||
throws ODataApplicationException {
|
||||
if (eTag != null) {
|
||||
final ETagInformation ifMatch = odata.createETagInformation(ifMatchHeaders);
|
||||
final ETagInformation ifNoneMatch = odata.createETagInformation(ifNoneMatchHeaders);
|
||||
if (!ifMatch.isMatchedBy(eTag) && !ifMatch.getETags().isEmpty()
|
||||
|| ifNoneMatch.isMatchedBy(eTag)) {
|
||||
throw new ODataApplicationException("The preconditions are not fulfilled.",
|
||||
HttpStatusCode.PRECONDITION_FAILED.getStatusCode(), Locale.ROOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,10 @@ 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.etag.CustomETagSupport;
|
||||
import org.apache.olingo.server.api.etag.PreconditionRequiredException;
|
||||
import org.apache.olingo.server.api.uri.UriInfo;
|
||||
import org.apache.olingo.server.core.etag.PreconditionsValidator;
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user