[OLINGO-659] Merge branch 'OLINGO-659_ReleaseFixes'
This commit is contained in:
commit
91bd50bc25
|
@ -29,13 +29,9 @@ public class DeletedEntity {
|
|||
* Reason of the removal from the list
|
||||
*/
|
||||
public enum Reason {
|
||||
/**
|
||||
* The entity was deleted
|
||||
*/
|
||||
/** The entity was deleted. */
|
||||
deleted,
|
||||
/**
|
||||
* The data of the entity as changed and not any longer part of the response
|
||||
*/
|
||||
/** The data of the entity has changed and is not any longer part of the response. */
|
||||
changed
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.apache.olingo.commons.api.data;
|
|||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Data representation for a operation.
|
||||
* Data representation for an operation.
|
||||
*/
|
||||
public class Operation {
|
||||
|
||||
|
|
|
@ -17,6 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
/**
|
||||
* Contains all the data objects of an OData responses and OData requests
|
||||
* Contains all the data objects of OData responses and OData requests
|
||||
*/
|
||||
package org.apache.olingo.commons.api.data;
|
|
@ -17,8 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
/**
|
||||
* Contains representations for all constants related
|
||||
* EDM objects created during the URI parsing
|
||||
* Contains representations for constants related to EDM objects.
|
||||
*/
|
||||
package org.apache.olingo.commons.api.edm.constants;
|
||||
|
||||
|
|
|
@ -43,9 +43,6 @@ public abstract class ComposedGeospatial<T extends Geospatial> extends Geospatia
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return this.geospatials.iterator();
|
||||
|
|
|
@ -17,6 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
/**
|
||||
* Contains all OData errors and exceptions related classes.
|
||||
* Contains all OData errors and exception-related classes.
|
||||
*/
|
||||
package org.apache.olingo.commons.api.ex;
|
|
@ -24,6 +24,7 @@ import java.util.Comparator;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Internally used {@link AcceptType} for OData library.
|
||||
|
@ -45,6 +46,8 @@ import java.util.Map;
|
|||
*/
|
||||
public final class AcceptType {
|
||||
|
||||
private static final Pattern Q_PATTERN = Pattern.compile("\\A(?:0(?:\\.\\d{0,3})?)|(?:1(?:\\.0{0,3})?)\\Z");
|
||||
|
||||
private final String type;
|
||||
private final String subtype;
|
||||
private final Map<String, String> parameters;
|
||||
|
@ -77,12 +80,10 @@ public final class AcceptType {
|
|||
final String q = parameters.get(TypeUtil.PARAMETER_Q);
|
||||
if (q == null) {
|
||||
quality = 1F;
|
||||
} else {
|
||||
try {
|
||||
} else if (Q_PATTERN.matcher(q).matches()) {
|
||||
quality = Float.valueOf(q);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Illegal quality parameter.", e);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Illegal quality parameter '" + q + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,9 @@ import java.util.Map;
|
|||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Helper class which is only used within this package (<code>AcceptType</code> and <code>ContentType</code> handling).
|
||||
* Helper class which is only used within this package.
|
||||
* @see AcceptType
|
||||
* @see ContentType
|
||||
*/
|
||||
final class TypeUtil {
|
||||
|
||||
|
@ -102,13 +104,15 @@ final class TypeUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Validate that parameter name and parameter value are valid .
|
||||
*
|
||||
* @param parameterName must be <code>not null</code>, <code>not empty</code> and <code>contains no whitespace
|
||||
* characters</code>
|
||||
* @param parameterValue must be <code>not null</code>, <code>not empty</code> and <code>not start with a whitespace
|
||||
* character</code>
|
||||
* @throws IllegalArgumentException if one of the above requirements are not met
|
||||
* Validates that parameter name and parameter value are valid:
|
||||
* <ul>
|
||||
* <li>not <code>null</code></li>
|
||||
* <li>not empty</li>
|
||||
* <li>does not contain whitespace characters (name), or does not start with whitespace (value), respectively</li>
|
||||
* </ul>
|
||||
* @param parameterName name
|
||||
* @param parameterValue value
|
||||
* @throws IllegalArgumentException if one of the above requirements is not met
|
||||
*/
|
||||
static void validateParameterNameAndValue(final String parameterName, final String parameterValue)
|
||||
throws IllegalArgumentException {
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
/**
|
||||
* Contains all the format related objects (also related to http headers <coder>Prefer</coder>, <code>Accepted</code>
|
||||
* and <code>Content-Type</code>) which are used for handling of an OData responses and OData requests.
|
||||
* Contains all the format-related objects used for the handling of
|
||||
* OData responses and OData requests.
|
||||
* They are related to the HTTP headers <code>Prefer</code>, <code>Accept</code>,
|
||||
* and <code>Content-Type</code>.
|
||||
*/
|
||||
package org.apache.olingo.commons.api.format;
|
|
@ -17,6 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
/**
|
||||
* Contains all the http related objects which are used for handling of an OData responses and OData requests.
|
||||
* Contains all the HTTP related objects which are used for handling of OData responses and OData requests.
|
||||
*/
|
||||
package org.apache.olingo.commons.api.http;
|
|
@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -31,7 +32,7 @@ import org.junit.Test;
|
|||
public class AcceptTypeTest {
|
||||
|
||||
@Test
|
||||
public void testWildcard() {
|
||||
public void wildcard() {
|
||||
List<AcceptType> atl = AcceptType.create("*/*");
|
||||
|
||||
assertEquals(1, atl.size());
|
||||
|
@ -42,7 +43,7 @@ public class AcceptTypeTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWildcardSubtype() {
|
||||
public void wildcardSubtype() {
|
||||
List<AcceptType> atl = AcceptType.create("a/*");
|
||||
|
||||
assertEquals(1, atl.size());
|
||||
|
@ -53,7 +54,7 @@ public class AcceptTypeTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSingleAcceptType() {
|
||||
public void singleAcceptType() {
|
||||
assertTrue(AcceptType.create("a/a").get(0).matches(ContentType.create("a/a")));
|
||||
assertTrue(AcceptType.create("a/a;q=0.2").get(0).matches(ContentType.create("a/a")));
|
||||
assertFalse(AcceptType.create("a/a;x=y;q=0.2").get(0).matches(ContentType.create("a/a")));
|
||||
|
@ -64,7 +65,7 @@ public class AcceptTypeTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptTypes() {
|
||||
public void acceptTypes() {
|
||||
List<AcceptType> atl;
|
||||
|
||||
atl = AcceptType.create("b/b,*/*,a/a,c/*");
|
||||
|
@ -101,53 +102,73 @@ public class AcceptTypeTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWithQParameter() {
|
||||
List<AcceptType> atl = AcceptType.create("application/json;q=0.2");
|
||||
public void withQParameter() {
|
||||
List<AcceptType> acceptTypes = AcceptType.create("application/json;q=0.2");
|
||||
|
||||
assertEquals(1, atl.size());
|
||||
assertEquals("application", atl.get(0).getType());
|
||||
assertEquals("json", atl.get(0).getSubtype());
|
||||
assertEquals("0.2", atl.get(0).getParameters().get("q"));
|
||||
assertEquals("application/json;q=0.2", atl.get(0).toString());
|
||||
assertEquals(1, acceptTypes.size());
|
||||
final AcceptType acceptType = acceptTypes.get(0);
|
||||
assertEquals("application", acceptType.getType());
|
||||
assertEquals("json", acceptType.getSubtype());
|
||||
assertEquals("0.2", acceptType.getParameters().get(TypeUtil.PARAMETER_Q));
|
||||
assertEquals("0.2", acceptType.getParameter(TypeUtil.PARAMETER_Q));
|
||||
assertEquals(Float.valueOf(0.2F), acceptType.getQuality());
|
||||
assertEquals("application/json;q=0.2", acceptType.toString());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void formatErrors() {
|
||||
expectCreateError("/");
|
||||
expectCreateError("//");
|
||||
expectCreateError("///");
|
||||
expectCreateError("a/b/c");
|
||||
expectCreateError("a//b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void abbreviationsNotAllowed() {
|
||||
AcceptType.create("application");
|
||||
expectCreateError("application");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWrongQParameter() {
|
||||
AcceptType.create(" a/a;q=z ");
|
||||
@Test
|
||||
public void wildcardError() {
|
||||
expectCreateError("*/json");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void incompleteParameter() {
|
||||
AcceptType.create("a/b;parameter");
|
||||
@Test
|
||||
public void wrongQParameter() {
|
||||
expectCreateError(" a/a;q=z ");
|
||||
expectCreateError("a/a;q=42");
|
||||
expectCreateError("a/a;q=0.0001");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void missingParameterValue() {
|
||||
AcceptType.create("a/b;parameter=");
|
||||
@Test
|
||||
public void parameterErrors() {
|
||||
expectCreateError("a/b;parameter");
|
||||
expectCreateError("a/b;parameter=");
|
||||
expectCreateError("a/b;name= value");
|
||||
expectCreateError("a/b;=value");
|
||||
expectCreateError("a/b;the name=value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void parameterValueStartingWithWhitespace() {
|
||||
AcceptType.create("a/b;name= value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void missingParameterName() {
|
||||
AcceptType.create("a/b;=value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void parameterNameWithWhitespace() {
|
||||
AcceptType.create("a/b;the name=value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void trailingSemicolon() {
|
||||
AcceptType.create("a/b;");
|
||||
expectCreateError("a/b;");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromContentType() {
|
||||
final List<AcceptType> acceptType = AcceptType.fromContentType(ContentType.APPLICATION_JSON);
|
||||
assertNotNull(acceptType);
|
||||
assertEquals(1, acceptType.size());
|
||||
assertEquals(ContentType.APPLICATION_JSON.toContentTypeString(), acceptType.get(0).toString());
|
||||
}
|
||||
|
||||
private void expectCreateError(final String value) {
|
||||
try {
|
||||
AcceptType.create(value);
|
||||
fail("Expected exception not thrown.");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
assertNotNull(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,10 @@ package org.apache.olingo.commons.api.format;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -36,44 +38,25 @@ public class ContentTypeTest {
|
|||
assertEquals(ContentType.create("A/B"), ContentType.create("a/b"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createFail1() {
|
||||
ContentType.create("a");
|
||||
}
|
||||
@Test
|
||||
public void createFail() {
|
||||
createWrong("a");
|
||||
createWrong(" a / b ");
|
||||
createWrong("a/b;");
|
||||
createWrong("a/b;parameter");
|
||||
createWrong("a/b;parameter=");
|
||||
createWrong("a/b;=value");
|
||||
createWrong("a/b;the name=value");
|
||||
createWrong("a/b;name= value");
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createFail2() {
|
||||
ContentType.create(" a / b ");
|
||||
}
|
||||
createWrong("*/*");
|
||||
createWrong("*");
|
||||
createWrong("a//b");
|
||||
createWrong("///");
|
||||
createWrong("a/*");
|
||||
createWrong("*/b");
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createFail3() {
|
||||
ContentType.create("a/b;");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createFail4() {
|
||||
ContentType.create("a/b;parameter");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createFail5() {
|
||||
ContentType.create("a/b;parameter=");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createFail6() {
|
||||
ContentType.create("a/b;=value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createFail7() {
|
||||
ContentType.create("a/b;the name=value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createFail8() {
|
||||
ContentType.create("a/b;name= value");
|
||||
createWrong(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -99,17 +82,14 @@ public class ContentTypeTest {
|
|||
|
||||
@Test
|
||||
public void parse() {
|
||||
assertEquals(ContentType.APPLICATION_OCTET_STREAM, ContentType.parse("application/octet-stream"));
|
||||
|
||||
assertNull(ContentType.parse("a"));
|
||||
assertNull(ContentType.parse("a/b;c"));
|
||||
assertNull(ContentType.parse("a/b;c="));
|
||||
assertNull(ContentType.parse("a/b;c= "));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void wildcardFail() {
|
||||
ContentType.create("*/*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void charsetUtf8() {
|
||||
ContentType ct1 = ContentType.create("a/b;charset=utf8");
|
||||
|
@ -118,8 +98,9 @@ public class ContentTypeTest {
|
|||
assertNotEquals(ct1, ct2);
|
||||
assertEquals(ct1.getType(), ct2.getType());
|
||||
assertEquals(ct1.getSubtype(), ct2.getSubtype());
|
||||
assertEquals("utf8", ct1.getParameters().get("charset"));
|
||||
assertEquals("utf-8", ct2.getParameters().get("charset"));
|
||||
assertEquals("utf8", ct1.getParameters().get(ContentType.PARAMETER_CHARSET));
|
||||
assertEquals("utf-8", ct2.getParameters().get(ContentType.PARAMETER_CHARSET));
|
||||
assertEquals("utf-8", ct2.getParameter(ContentType.PARAMETER_CHARSET));
|
||||
|
||||
assertTrue(ct1.isCompatible(ct2));
|
||||
}
|
||||
|
@ -130,4 +111,13 @@ public class ContentTypeTest {
|
|||
ContentType.create(ContentType.create(ContentType.APPLICATION_JSON, "a", "b"), "c", "d")
|
||||
.toContentTypeString());
|
||||
}
|
||||
|
||||
private void createWrong(final String value) {
|
||||
try {
|
||||
ContentType.create(value);
|
||||
fail("Expected exception not thrown.");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
assertNotNull(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* HttpHeader container.
|
||||
* HttpHeader container for internal use in this package.
|
||||
* @see ODataRequest
|
||||
* @see ODataResponse
|
||||
*/
|
||||
public class HttpHeaders {
|
||||
final class HttpHeaders {
|
||||
private final Map<String, List<String>> headers = new LinkedHashMap<String, List<String>>();
|
||||
|
||||
/**
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ODataRequest {
|
|||
}
|
||||
|
||||
/**
|
||||
* <p>Set a header to the response.</p>
|
||||
* <p>Sets a header in the request.</p>
|
||||
* <p>The header name will be handled as case-insensitive key.</p>
|
||||
* <p>If a header already exists then the header will be replaced by this new value.</p>
|
||||
* @param name case-insensitive header name
|
||||
|
|
|
@ -18,20 +18,17 @@
|
|||
*/
|
||||
/**
|
||||
* Olingo Server API
|
||||
* <p>
|
||||
* OData Library is a protocol implementation of the OData V4.0 standard. For details of this standard
|
||||
* see <a href="http://odata.org">odata.org</a>.
|
||||
* <p>
|
||||
* This API is intended to help implement an OData service. An OData service consists of a metadata provider
|
||||
* implementation and an OData processor implementation.
|
||||
* <p>
|
||||
* An OData service can be exposed by a web application using the standard java servlet API. See the Olingo tutorials
|
||||
* section on how to implement a V4 service for further information:
|
||||
* <a href="http://olingo.apache.org/doc/odata4/index.html">http://olingo.apache.org/doc/odata4/index.html
|
||||
* <p>
|
||||
* The main entry point is the org.apache.olingo.server.api.OData class. Use the newInstance() method to create a new
|
||||
* object and start providing your service from there.
|
||||
*
|
||||
* <p>The OData Library is a protocol implementation of the OData V4.0 standard.
|
||||
* For details of this standard see <a href="http://odata.org">odata.org</a>.</p>
|
||||
* <p>This API is intended to help implementing an OData service.
|
||||
* An OData service consists of a metadata provider implementation and an
|
||||
* OData processor implementation.</p>
|
||||
* <p>An OData service can be exposed by a web application using the standard java servlet API.
|
||||
* For further information, see the <a href="http://olingo.apache.org/doc/odata4/">Olingo
|
||||
* tutorials</a> on how to implement an OData service.</p>
|
||||
* <p>The main entry point is the org.apache.olingo.server.api.OData class.
|
||||
* Use the newInstance() method to create a new object and
|
||||
* start providing your service from there.</p>
|
||||
*/
|
||||
package org.apache.olingo.server.api;
|
||||
|
||||
|
|
|
@ -18,17 +18,17 @@
|
|||
*/
|
||||
/**
|
||||
* Olingo Processors
|
||||
* <p>
|
||||
* Processors are used to handle OData requests and send back the OData reponse. Before a specific processor is called
|
||||
* the Olingo library will parse the URI and validate it. Afterwards the Processor which matches the return type is
|
||||
* called. E.g.: If a primitive property is requested by the URI we will call the PrimitveProcessor.read method.
|
||||
* <p>
|
||||
* Processors can be registered at the {@link org.apache.olingo.server.api.ODataHttpHandler} object. Per default we will
|
||||
* have the {@link org.apache.olingo.server.api.processor.DefaultProcessor} registered to perform basic functionality
|
||||
* like delivering the metadata and service document as well as rendering an OData error.
|
||||
* <br>In case an application would like to perform custom tasks for these cases a new
|
||||
* {@link org.apache.olingo.server.api.processor.ServiceDocumentProcessor} can be registered in order to overwrite the
|
||||
* default behaviour.
|
||||
* <p>Processors are used to handle OData requests and send back the OData reponse.
|
||||
* Before a specific processor is called the Olingo library will parse the URI and validate it.
|
||||
* Afterwards the Processor which matches the return type is called.
|
||||
* Example: If a primitive property is requested by the URI we will call the
|
||||
* PrimitiveProcessor.readPrimitive method.</p>
|
||||
* <p>Processors can be registered at the {@link org.apache.olingo.server.api.ODataHttpHandler} object.
|
||||
* Per default the {@link org.apache.olingo.server.api.processor.DefaultProcessor} is registered
|
||||
* to perform basic functionality like delivering the metadata and service documents, respectively,
|
||||
* as well as rendering an OData error.
|
||||
* In case an application would like to perform custom tasks for these cases a new
|
||||
* {@link org.apache.olingo.server.api.processor.ServiceDocumentProcessor} can be registered
|
||||
* in order to overwrite the default behavior.
|
||||
*/
|
||||
package org.apache.olingo.server.api.processor;
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@ public final class ContentNegotiator {
|
|||
private static final String XML = "xml";
|
||||
|
||||
private static final List<ContentType> DEFAULT_SUPPORTED_CONTENT_TYPES =
|
||||
Collections.unmodifiableList(Arrays.asList(
|
||||
ContentType.JSON,
|
||||
ContentType.JSON_NO_METADATA,
|
||||
ContentType.APPLICATION_JSON,
|
||||
ContentType.APPLICATION_ATOM_XML,
|
||||
ContentType.APPLICATION_XML));
|
||||
Collections.unmodifiableList(Arrays.asList(
|
||||
ContentType.JSON,
|
||||
ContentType.JSON_NO_METADATA,
|
||||
ContentType.APPLICATION_JSON,
|
||||
ContentType.APPLICATION_ATOM_XML,
|
||||
ContentType.APPLICATION_XML));
|
||||
|
||||
private ContentNegotiator() {}
|
||||
|
||||
|
@ -102,17 +102,15 @@ public final class ContentNegotiator {
|
|||
ContentNegotiatorException.MessageKeys.UNSUPPORTED_FORMAT_OPTION, formatString);
|
||||
}
|
||||
} else if (acceptHeaderValue != null) {
|
||||
final List<AcceptType> acceptedContentTypes = AcceptType.create(acceptHeaderValue);
|
||||
try {
|
||||
result = getAcceptedType(acceptedContentTypes, supportedContentTypes);
|
||||
result = getAcceptedType(AcceptType.create(acceptHeaderValue), supportedContentTypes);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw new ContentNegotiatorException("charset in accept header not supported: " + acceptHeaderValue, e,
|
||||
ContentNegotiatorException.MessageKeys.WRONG_CHARSET_IN_HEADER, HttpHeader.ACCEPT, acceptHeaderValue);
|
||||
result = null;
|
||||
}
|
||||
if (result == null) {
|
||||
throw new ContentNegotiatorException(
|
||||
"unsupported accept content type: " + acceptedContentTypes + " != " + supportedContentTypes,
|
||||
ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPES, acceptedContentTypes.toString());
|
||||
"Unsupported or illegal Accept header value: " + acceptHeaderValue + " != " + supportedContentTypes,
|
||||
ContentNegotiatorException.MessageKeys.UNSUPPORTED_ACCEPT_TYPES, acceptHeaderValue);
|
||||
}
|
||||
} else {
|
||||
final ContentType requestedContentType = getDefaultSupportedContentTypes(representationType).get(0);
|
||||
|
@ -127,7 +125,7 @@ public final class ContentNegotiator {
|
|||
return result;
|
||||
}
|
||||
|
||||
private static ContentType mapContentType(String formatString) {
|
||||
private static ContentType mapContentType(final String formatString) {
|
||||
return JSON.equalsIgnoreCase(formatString) ? ContentType.JSON :
|
||||
XML.equalsIgnoreCase(formatString) ? ContentType.APPLICATION_XML :
|
||||
ATOM.equalsIgnoreCase(formatString) ? ContentType.APPLICATION_ATOM_XML : null;
|
||||
|
|
|
@ -24,10 +24,8 @@ public class ContentNegotiatorException extends ODataLibraryException {
|
|||
private static final long serialVersionUID = -8112658467394158700L;
|
||||
|
||||
public static enum MessageKeys implements MessageKey {
|
||||
/** parameters: HTTP header name, HTTP header value */
|
||||
WRONG_CHARSET_IN_HEADER,
|
||||
/** parameter: list of content-type ranges */
|
||||
UNSUPPORTED_CONTENT_TYPES,
|
||||
UNSUPPORTED_ACCEPT_TYPES,
|
||||
/** parameter: content type */
|
||||
UNSUPPORTED_CONTENT_TYPE,
|
||||
/** no parameter */
|
||||
|
|
|
@ -297,15 +297,10 @@ public class ODataDispatcher {
|
|||
.deleteReference(request, response, uriInfo);
|
||||
|
||||
} else {
|
||||
throw new ODataHandlerException(getMethodNotAllowedStringMessage(httpMethod),
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, httpMethod.toString());
|
||||
throwMethodNotAllowed(httpMethod);
|
||||
}
|
||||
}
|
||||
|
||||
private String getMethodNotAllowedStringMessage(final HttpMethod httpMethod) {
|
||||
return "HTTP method " + httpMethod + " is not allowed.";
|
||||
}
|
||||
|
||||
private void handleValueDispatching(final ODataRequest request, final ODataResponse response,
|
||||
final int lastPathSegmentIndex) throws ODataApplicationException, ODataLibraryException {
|
||||
final HttpMethod method = request.getMethod();
|
||||
|
@ -337,8 +332,7 @@ public class ODataDispatcher {
|
|||
handler.selectProcessor(PrimitiveValueProcessor.class)
|
||||
.deletePrimitiveValue(request, response, uriInfo);
|
||||
} else {
|
||||
throw new ODataHandlerException(getMethodNotAllowedStringMessage(method),
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
|
||||
throwMethodNotAllowed(method);
|
||||
}
|
||||
} else {
|
||||
if (method == HttpMethod.GET) {
|
||||
|
@ -358,8 +352,7 @@ public class ODataDispatcher {
|
|||
handler.selectProcessor(MediaEntityProcessor.class)
|
||||
.deleteMediaEntity(request, response, uriInfo);
|
||||
} else {
|
||||
throw new ODataHandlerException(getMethodNotAllowedStringMessage(method),
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
|
||||
throwMethodNotAllowed(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,8 +395,7 @@ public class ODataDispatcher {
|
|||
.deleteComplex(request, response, uriInfo);
|
||||
}
|
||||
} else {
|
||||
throw new ODataHandlerException(getMethodNotAllowedStringMessage(method),
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
|
||||
throwMethodNotAllowed(method);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,8 +437,7 @@ public class ODataDispatcher {
|
|||
.deletePrimitive(request, response, uriInfo);
|
||||
}
|
||||
} else {
|
||||
throw new ODataHandlerException(getMethodNotAllowedStringMessage(method),
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
|
||||
throwMethodNotAllowed(method);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,8 +484,7 @@ public class ODataDispatcher {
|
|||
.createEntity(request, response, uriInfo, requestFormat, responseFormat);
|
||||
}
|
||||
} else {
|
||||
throw new ODataHandlerException(getMethodNotAllowedStringMessage(method),
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
|
||||
throwMethodNotAllowed(method);
|
||||
}
|
||||
} else {
|
||||
if (method == HttpMethod.GET) {
|
||||
|
@ -515,8 +505,7 @@ public class ODataDispatcher {
|
|||
handler.selectProcessor(isMedia ? MediaEntityProcessor.class : EntityProcessor.class)
|
||||
.deleteEntity(request, response, uriInfo);
|
||||
} else {
|
||||
throw new ODataHandlerException(getMethodNotAllowedStringMessage(method),
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
|
||||
throwMethodNotAllowed(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -537,11 +526,15 @@ public class ODataDispatcher {
|
|||
private void checkMethod(final HttpMethod requestMethod, final HttpMethod allowedMethod)
|
||||
throws ODataHandlerException {
|
||||
if (requestMethod != allowedMethod) {
|
||||
throw new ODataHandlerException(getMethodNotAllowedStringMessage(requestMethod),
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, requestMethod.toString());
|
||||
throwMethodNotAllowed(requestMethod);
|
||||
}
|
||||
}
|
||||
|
||||
private void throwMethodNotAllowed(final HttpMethod httpMethod) throws ODataHandlerException {
|
||||
throw new ODataHandlerException("HTTP method " + httpMethod + " is not allowed.",
|
||||
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, httpMethod.toString());
|
||||
}
|
||||
|
||||
private ContentType getSupportedContentType(final String contentTypeHeader,
|
||||
final RepresentationType representationType, final boolean mustNotBeNull)
|
||||
throws ODataHandlerException, ContentNegotiatorException {
|
||||
|
@ -551,7 +544,13 @@ public class ODataDispatcher {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
final ContentType contentType = ContentType.parse(contentTypeHeader);
|
||||
ContentType contentType;
|
||||
try {
|
||||
contentType = ContentType.create(contentTypeHeader);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw new ODataHandlerException("Illegal content type.", e,
|
||||
ODataHandlerException.MessageKeys.INVALID_CONTENT_TYPE, contentTypeHeader);
|
||||
}
|
||||
ContentNegotiator.checkSupport(contentType, handler.getCustomContentTypeSupport(), representationType);
|
||||
return contentType;
|
||||
}
|
||||
|
|
|
@ -91,7 +91,8 @@ public class ODataExceptionHelper {
|
|||
} else if (ODataHandlerException.MessageKeys.ODATA_VERSION_NOT_SUPPORTED.equals(e.getMessageKey())
|
||||
|| ODataHandlerException.MessageKeys.INVALID_HTTP_METHOD.equals(e.getMessageKey())
|
||||
|| ODataHandlerException.MessageKeys.AMBIGUOUS_XHTTP_METHOD.equals(e.getMessageKey())
|
||||
|| ODataHandlerException.MessageKeys.MISSING_CONTENT_TYPE.equals(e.getMessageKey())) {
|
||||
|| ODataHandlerException.MessageKeys.MISSING_CONTENT_TYPE.equals(e.getMessageKey())
|
||||
|| ODataHandlerException.MessageKeys.INVALID_CONTENT_TYPE.equals(e.getMessageKey())) {
|
||||
serverError.setStatusCode(HttpStatusCode.BAD_REQUEST.getStatusCode());
|
||||
} else if (ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED.equals(e.getMessageKey())) {
|
||||
serverError.setStatusCode(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode());
|
||||
|
|
|
@ -39,6 +39,8 @@ public class ODataHandlerException extends ODataLibraryException {
|
|||
MISSING_CONTENT_TYPE,
|
||||
/** parameter: content type */
|
||||
UNSUPPORTED_CONTENT_TYPE,
|
||||
/** parameter: content type */
|
||||
INVALID_CONTENT_TYPE,
|
||||
/** parameter: version */
|
||||
ODATA_VERSION_NOT_SUPPORTED;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ ODataHandlerException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested functionality
|
|||
ODataHandlerException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported.
|
||||
ODataHandlerException.MISSING_CONTENT_TYPE=The Content-Type HTTP header must be specified for this request.
|
||||
ODataHandlerException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported for this request.
|
||||
ODataHandlerException.INVALID_CONTENT_TYPE=The content type '%1$s' is not valid.
|
||||
|
||||
UriParserSyntaxException.MUST_BE_LAST_SEGMENT=The segment '%1$s' must be the last segment.
|
||||
UriParserSyntaxException.UNKNOWN_SYSTEM_QUERY_OPTION=The system query option '%1$s' is not defined.
|
||||
|
@ -81,8 +82,7 @@ UriValidationException.SECOND_LAST_SEGMENT_NOT_TYPED=The second last segment '%1
|
|||
UriValidationException.UNALLOWED_KIND_BEFORE_VALUE=The kind '%1$s' is not allowed before '$value'.
|
||||
UriValidationException.UNALLOWED_KIND_BEFORE_COUNT=The kind '%1$s' is not allowed before '$count'.
|
||||
|
||||
ContentNegotiatorException.WRONG_CHARSET_IN_HEADER=The HTTP header '%1$s' with value '%2$s' contains an invalid character-set specification.
|
||||
ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPES=The content-type range '%1$s' is not supported.
|
||||
ContentNegotiatorException.UNSUPPORTED_ACCEPT_TYPES=The content-type range '%1$s' is not supported as value of the Accept header.
|
||||
ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported.
|
||||
ContentNegotiatorException.NO_CONTENT_TYPE_SUPPORTED=No content type has been specified as supported.
|
||||
ContentNegotiatorException.UNSUPPORTED_FORMAT_OPTION=The $format option '%1$s' is not supported.
|
||||
|
|
|
@ -40,19 +40,18 @@ import org.junit.Test;
|
|||
|
||||
public class ContentNegotiatorTest {
|
||||
|
||||
static final private String ACCEPT_CASE_MIN = "application/json;odata.metadata=minimal";
|
||||
static final private String ACCEPT_CASE_MIN = ContentType.JSON.toContentTypeString();
|
||||
static final private String ACCEPT_CASE_MIN_UTF8 = "application/json;charset=UTF-8;odata.metadata=minimal";
|
||||
static final private String ACCEPT_CASE_FULL = "application/json;odata.metadata=full";
|
||||
static final private String ACCEPT_CASE_NONE = "application/json;odata.metadata=none";
|
||||
static final private String ACCEPT_CASE_FULL = ContentType.JSON_FULL_METADATA.toContentTypeString();
|
||||
static final private String ACCEPT_CASE_NONE = ContentType.JSON_NO_METADATA.toContentTypeString();
|
||||
static final private String ACCEPT_CASE_MIN_UTF8_IEEE754 =
|
||||
"application/json;charset=UTF-8;odata.metadata=minimal;IEEE754Compatible=true";
|
||||
static final private String ACCEPT_CASE_MIN_IEEE754 =
|
||||
"application/json;odata.metadata=minimal;IEEE754Compatible=true";
|
||||
static final private String ACCEPT_CASE_MIN_IEEE754 = ACCEPT_CASE_MIN + ";IEEE754Compatible=true";
|
||||
static final private String ACCEPT_CASE_JSONQ = "application/json;q=0.2";
|
||||
static final private String ACCEPT_CASE_XML = ContentType.APPLICATION_XML.toContentTypeString();
|
||||
static final private String ACCEPT_CASE_WILDCARD1 = "*/*";
|
||||
static final private String ACCEPT_CASE_WILDCARD2 = "application/*";
|
||||
|
||||
|
||||
//@formatter:off (Eclipse formatter)
|
||||
//CHECKSTYLE:OFF (Maven checkstyle)
|
||||
|
||||
|
@ -101,6 +100,7 @@ public class ContentNegotiatorTest {
|
|||
{ null, "a/a;x=y", null, "a/a;v=w" },
|
||||
{ null, null, "a/a;x=y", "a/a;v=w" },
|
||||
{ null, null, ACCEPT_CASE_FULL, null }, // not yet supported
|
||||
{ null, null, "*", null },
|
||||
{ null, "a/b;charset=ISO-8859-1", null, "a/b" },
|
||||
{ null, null, "a/b;charset=ISO-8859-1", "a/b" },
|
||||
{ null, null, null, "text/plain" }
|
||||
|
@ -153,8 +153,7 @@ public class ContentNegotiatorTest {
|
|||
|
||||
@Test
|
||||
public void checkSupport() throws Exception {
|
||||
ContentNegotiator.checkSupport(ContentType.JSON, null,
|
||||
RepresentationType.ENTITY);
|
||||
ContentNegotiator.checkSupport(ContentType.JSON, null, RepresentationType.ENTITY);
|
||||
ContentNegotiator.checkSupport(ContentType.TEXT_PLAIN, null, RepresentationType.VALUE);
|
||||
try {
|
||||
ContentNegotiator.checkSupport(ContentType.APPLICATION_SVG_XML, null, RepresentationType.ENTITY);
|
||||
|
|
|
@ -695,6 +695,15 @@ public class ODataHandlerTest {
|
|||
assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void illegalRequestContentType() throws Exception {
|
||||
EntityProcessor processor = mock(EntityProcessor.class);
|
||||
final ODataResponse response = dispatch(HttpMethod.POST, "ESAllPrim", null,
|
||||
HttpHeader.CONTENT_TYPE, "*/*", processor);
|
||||
verifyZeroInteractions(processor);
|
||||
assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unsupportedRequestContentType() throws Exception {
|
||||
EntityProcessor processor = mock(EntityProcessor.class);
|
||||
|
|
Loading…
Reference in New Issue