This is an automated email from the git hooks/post-receive script. tjaalton pushed a commit to branch master in repository jackson-jaxrs-providers.
commit 0551d471af63753b9f83afcc3e572a3a8baafdec Author: Tatu Saloranta <[email protected]> Date: Sat Mar 16 11:36:24 2013 -0700 refactoring --- .../jaxrs/base/JsonMappingExceptionMapper.java | 1 + .../jaxrs/base/JsonParseExceptionMapper.java | 1 + .../fasterxml/jackson/jaxrs/base/ProviderBase.java | 25 +- .../jackson/jaxrs/base/cfg/EndpointConfigBase.java | 13 + .../jackson/jaxrs/base/util/ClassKey.java | 2 +- .../jackson/jaxrs/json/JacksonJsonProvider.java | 1 + .../jackson/jaxrs/json/JsonEndpointConfig.java | 16 +- .../jackson/jaxrs/json/JsonMapperConfigurator.java | 1 + .../jaxrs/json/JsonMappingExceptionMapper.java | 1 + .../jaxrs/json/JsonParseExceptionMapper.java | 1 + .../jackson/jaxrs/json/TestStreamingOutput.java | 1 + .../jackson/jaxrs/json/TestUntouchables.java | 1 + .../jackson/jaxrs/smile/JacksonSmileProvider.java | 2 + .../jaxrs/smile/JsonMappingExceptionMapper.java | 1 + .../jaxrs/smile/JsonParseExceptionMapper.java | 1 + .../jackson/jaxrs/smile/SmileEndpointConfig.java | 19 + .../jaxrs/smile/SmileMapperConfigurator.java | 2 + .../jackson/jaxrs/xml/JacksonXMLProvider.java | 557 ++------------------- .../jaxrs/xml/JsonMappingExceptionMapper.java | 1 + .../jaxrs/xml/JsonParseExceptionMapper.java | 1 + .../jackson/jaxrs/xml/XMLEndpointConfig.java | 160 +----- .../jackson/jaxrs/xml/XMLMapperConfigurator.java | 2 + .../jackson/jaxrs/xml/TestUntouchables.java | 2 +- 23 files changed, 131 insertions(+), 681 deletions(-) diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/JsonMappingExceptionMapper.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/JsonMappingExceptionMapper.java index 2e9a060..e03a2a1 100644 --- a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/JsonMappingExceptionMapper.java +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/JsonMappingExceptionMapper.java @@ -14,6 +14,7 @@ import javax.ws.rs.ext.Provider; */ @Provider public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> { + @Override public Response toResponse(JsonMappingException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); } diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/JsonParseExceptionMapper.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/JsonParseExceptionMapper.java index 55b0d0d..9a34ae7 100644 --- a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/JsonParseExceptionMapper.java +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/JsonParseExceptionMapper.java @@ -14,6 +14,7 @@ import javax.ws.rs.ext.Provider; */ @Provider public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> { + @Override public Response toResponse(JsonParseException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); } diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java index 61f59ff..9fe0563 100644 --- a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java @@ -309,6 +309,7 @@ public abstract class ProviderBase< * that container will determine length from actual serialized * output (if needed). */ + @Override public long getSize(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { /* In general figuring output size requires actual writing; usually not @@ -328,6 +329,7 @@ public abstract class ProviderBase< * for type (iff {@link #checkCanSerialize} has been called with * true argument -- otherwise assumption is there will be a handler) */ + @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { if (!hasMatchingMediaType(mediaType)) { @@ -363,6 +365,7 @@ public abstract class ProviderBase< /** * Method that JAX-RS container calls to serialize given value. */ + @Override public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream) throws IOException @@ -453,6 +456,7 @@ public abstract class ProviderBase< * for type (iff {@link #checkCanDeserialize} has been called with * true argument -- otherwise assumption is there will be a handler) */ + @Override public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { if (!hasMatchingMediaType(mediaType)) { @@ -489,6 +493,7 @@ public abstract class ProviderBase< /** * Method that JAX-RS container calls to deserialize given value. */ + @Override public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,String> httpHeaders, InputStream entityStream) throws IOException { @@ -507,13 +512,25 @@ public abstract class ProviderBase< } } ObjectReader reader = endpoint.getReader(); - - JsonParser jp = reader.getFactory().createParser(entityStream); - if (jp.nextToken() == null) { - return null; + JsonParser jp = _createParser(reader, entityStream); + // If null is returned, considered to be empty stream + if (jp == null || jp.nextToken() == null) { + return null; } return reader.withType(genericType).readValue(jp); } + + /** + * Overridable helper method called to create a {@link JsonParser} for reading + * contents of given raw {@link InputStream}. + * May return null to indicate that Stream is empty; that is, contains no + * content. + */ + protected JsonParser _createParser(ObjectReader reader, InputStream rawStream) + throws IOException + { + return reader.getFactory().createParser(rawStream); + } /* /********************************************************** diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/cfg/EndpointConfigBase.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/cfg/EndpointConfigBase.java index da7ec2a..76b56ec 100644 --- a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/cfg/EndpointConfigBase.java +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/cfg/EndpointConfigBase.java @@ -162,4 +162,17 @@ public abstract class EndpointConfigBase<THIS extends EndpointConfigBase<THIS>> */ public abstract Object modifyBeforeWrite(Object value); + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected static <T> T[] nullIfEmpty(T[] arg) { + if (arg == null || arg.length == 0) { + return null; + } + return arg; + } } diff --git a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/util/ClassKey.java b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/util/ClassKey.java index 587d48a..1ee6327 100644 --- a/base/src/main/java/com/fasterxml/jackson/jaxrs/base/util/ClassKey.java +++ b/base/src/main/java/com/fasterxml/jackson/jaxrs/base/util/ClassKey.java @@ -56,7 +56,7 @@ public final class ClassKey */ // Just need to sort by name, ok to collide (unless used in TreeMap/Set!) - //@Override + @Override public int compareTo(ClassKey other) { return _className.compareTo(other._className); } diff --git a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JacksonJsonProvider.java b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JacksonJsonProvider.java index a65d5c8..1aad274 100644 --- a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JacksonJsonProvider.java +++ b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JacksonJsonProvider.java @@ -129,6 +129,7 @@ public class JacksonJsonProvider * Method that will return version information stored in and read from jar * that contains this class. */ + @Override public Version version() { return PackageVersion.VERSION; } diff --git a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonEndpointConfig.java b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonEndpointConfig.java index 6475d96..1b0b4e6 100644 --- a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonEndpointConfig.java +++ b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonEndpointConfig.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.util.JSONWrappedObject; import com.fasterxml.jackson.jaxrs.base.cfg.EndpointConfigBase; import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; import com.fasterxml.jackson.jaxrs.json.annotation.JacksonFeatures; -import com.fasterxml.jackson.jaxrs.json.annotation.JSONP.Def; /** * Container class for figuring out annotation-based configuration @@ -55,7 +54,7 @@ public class JsonEndpointConfig /* Abstract method impls, overrides /********************************************************** */ - + @Override protected void addAnnotation(Class<? extends Annotation> type, Annotation annotation, boolean forWriting) @@ -106,17 +105,4 @@ public class JsonEndpointConfig } return value; } - - /* - /********************************************************** - /* Helper methods - /********************************************************** - */ - - private static <T> T[] nullIfEmpty(T[] arg) { - if (arg == null || arg.length == 0) { - return null; - } - return arg; - } } diff --git a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonMapperConfigurator.java b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonMapperConfigurator.java index d19ade8..d3824d3 100644 --- a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonMapperConfigurator.java +++ b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonMapperConfigurator.java @@ -73,6 +73,7 @@ public class JsonMapperConfigurator /********************************************************** */ + @Override protected AnnotationIntrospector _resolveIntrospectors(Annotations[] annotationsToUse) { // Let's ensure there are no dups there first, filter out nulls diff --git a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonMappingExceptionMapper.java b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonMappingExceptionMapper.java index 7926ac2..a195f93 100644 --- a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonMappingExceptionMapper.java +++ b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonMappingExceptionMapper.java @@ -12,6 +12,7 @@ import javax.ws.rs.ext.Provider; @Deprecated @Provider public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> { + @Override public Response toResponse(JsonMappingException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); } diff --git a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonParseExceptionMapper.java b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonParseExceptionMapper.java index d51b9d8..28e70ff 100644 --- a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonParseExceptionMapper.java +++ b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/JsonParseExceptionMapper.java @@ -12,6 +12,7 @@ import javax.ws.rs.ext.Provider; @Deprecated @Provider public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> { + @Override public Response toResponse(JsonParseException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); } diff --git a/json/src/test/java/com/fasterxml/jackson/jaxrs/json/TestStreamingOutput.java b/json/src/test/java/com/fasterxml/jackson/jaxrs/json/TestStreamingOutput.java index 52aa90d..4d78cf7 100644 --- a/json/src/test/java/com/fasterxml/jackson/jaxrs/json/TestStreamingOutput.java +++ b/json/src/test/java/com/fasterxml/jackson/jaxrs/json/TestStreamingOutput.java @@ -13,6 +13,7 @@ public class TestStreamingOutput extends JaxrsTestBase // important: this can trick "canSerialize()" to include it: public int getFoo() { return 3; } + @Override public void write(OutputStream out) throws IOException { out.write("OK".getBytes("UTF-8")); } diff --git a/json/src/test/java/com/fasterxml/jackson/jaxrs/json/TestUntouchables.java b/json/src/test/java/com/fasterxml/jackson/jaxrs/json/TestUntouchables.java index 1a180cb..ab741bf 100644 --- a/json/src/test/java/com/fasterxml/jackson/jaxrs/json/TestUntouchables.java +++ b/json/src/test/java/com/fasterxml/jackson/jaxrs/json/TestUntouchables.java @@ -27,6 +27,7 @@ public class TestUntouchables } static class StreamingSubType implements StreamingOutput { + @Override public void write(OutputStream output) { } } diff --git a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JacksonSmileProvider.java b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JacksonSmileProvider.java index 06e92da..74ea46c 100644 --- a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JacksonSmileProvider.java +++ b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JacksonSmileProvider.java @@ -118,6 +118,7 @@ extends ProviderBase<JacksonSmileProvider, * Method that will return version information stored in and read from jar * that contains this class. */ + @Override public Version version() { return PackageVersion.VERSION; } @@ -184,6 +185,7 @@ extends ProviderBase<JacksonSmileProvider, * not used by this method, * but will be passed to {@link ContextResolver} as is. */ + @Override protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType) { if (_providers != null) { diff --git a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JsonMappingExceptionMapper.java b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JsonMappingExceptionMapper.java index d03d9a3..b1bbbd0 100644 --- a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JsonMappingExceptionMapper.java +++ b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JsonMappingExceptionMapper.java @@ -12,6 +12,7 @@ import javax.ws.rs.ext.Provider; */ @Provider public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> { + @Override public Response toResponse(JsonMappingException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); } diff --git a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JsonParseExceptionMapper.java b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JsonParseExceptionMapper.java index c3037ee..1787f99 100644 --- a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JsonParseExceptionMapper.java +++ b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/JsonParseExceptionMapper.java @@ -12,6 +12,7 @@ import javax.ws.rs.ext.Provider; */ @Provider public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> { + @Override public Response toResponse(JsonParseException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); } diff --git a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/SmileEndpointConfig.java b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/SmileEndpointConfig.java index 29c8644..35a1bb7 100644 --- a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/SmileEndpointConfig.java +++ b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/SmileEndpointConfig.java @@ -4,6 +4,7 @@ import java.lang.annotation.Annotation; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.jaxrs.base.cfg.EndpointConfigBase; +import com.fasterxml.jackson.jaxrs.smile.annotation.JacksonFeatures; /** * Container class for figuring out annotation-based configuration @@ -37,6 +38,24 @@ public class SmileEndpointConfig } @Override + protected void addAnnotation(Class<? extends Annotation> type, + Annotation annotation, boolean forWriting) + { + if (type == JacksonFeatures.class) { + JacksonFeatures feats = (JacksonFeatures) annotation; + if (forWriting) { + _serEnable = nullIfEmpty(feats.serializationEnable()); + _serDisable = nullIfEmpty(feats.serializationDisable()); + } else { + _deserEnable = nullIfEmpty(feats.deserializationEnable()); + _deserDisable = nullIfEmpty(feats.deserializationDisable()); + } + } else { + super.addAnnotation(type, annotation, forWriting); + } + } + + @Override public Object modifyBeforeWrite(Object value) { // nothing to add return value; diff --git a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/SmileMapperConfigurator.java b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/SmileMapperConfigurator.java index 0807876..70d9bce 100644 --- a/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/SmileMapperConfigurator.java +++ b/smile/src/main/java/com/fasterxml/jackson/jaxrs/smile/SmileMapperConfigurator.java @@ -32,6 +32,7 @@ public class SmileMapperConfigurator /** * Method that locates, configures and returns {@link ObjectMapper} to use */ + @Override public synchronized ObjectMapper getConfiguredMapper() { /* important: should NOT call mapper(); needs to return null * if no instance has been passed or constructed @@ -39,6 +40,7 @@ public class SmileMapperConfigurator return _mapper; } + @Override public synchronized ObjectMapper getDefaultMapper() { if (_defaultMapper == null) { _defaultMapper = new ObjectMapper(new SmileFactory()); diff --git a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JacksonXMLProvider.java b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JacksonXMLProvider.java index 6d21a7f..e996367 100644 --- a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JacksonXMLProvider.java +++ b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JacksonXMLProvider.java @@ -2,25 +2,17 @@ package com.fasterxml.jackson.jaxrs.xml; import java.io.*; import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.*; import javax.ws.rs.*; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.ext.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.util.LRUMap; import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import com.fasterxml.jackson.jaxrs.base.util.AnnotationBundleKey; -import com.fasterxml.jackson.jaxrs.base.util.ClassKey; - +import com.fasterxml.jackson.jaxrs.base.ProviderBase; /** * Basic implementation of JAX-RS abstractions ({@link MessageBodyReader}, @@ -56,10 +48,11 @@ import com.fasterxml.jackson.jaxrs.base.util.ClassKey; @Consumes({MediaType.TEXT_XML, MediaType.APPLICATION_XML}) @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML}) public class JacksonXMLProvider - implements - MessageBodyReader<Object>, - MessageBodyWriter<Object>, - Versioned + extends ProviderBase<JacksonXMLProvider, + XmlMapper, Annotations, + XMLEndpointConfig, + XMLMapperConfigurator +> { /** * Default annotation sets to use, if not explicitly defined during @@ -69,91 +62,6 @@ public class JacksonXMLProvider public final static Annotations[] BASIC_ANNOTATIONS = { Annotations.JACKSON }; - - /** - * Looks like we need to worry about accidental - * data binding for types we shouldn't be handling. This is - * probably not a very good way to do it, but let's start by - * blacklisting things we are not to handle. - *<p> - * (why ClassKey? since plain old Class has no hashCode() defined, - * lookups are painfully slow) - */ - public final static HashSet<ClassKey> _untouchables = new HashSet<ClassKey>(); - static { - // First, I/O things (direct matches) - _untouchables.add(new ClassKey(java.io.InputStream.class)); - _untouchables.add(new ClassKey(java.io.Reader.class)); - _untouchables.add(new ClassKey(java.io.OutputStream.class)); - _untouchables.add(new ClassKey(java.io.Writer.class)); - - // then some primitive types - _untouchables.add(new ClassKey(char[].class)); - - /* 27-Apr-2012, tatu: Grrrh. Looks like we need to consider these - * untouchables, still, to allow users to access "raw" responses - * if and as necessary. Latter is unfortunate in a way as it - * prevents use of automatic base64 decoding but... - */ - _untouchables.add(new ClassKey(String.class)); - _untouchables.add(new ClassKey(byte[].class)); - - // Then core JAX-RS things - _untouchables.add(new ClassKey(StreamingOutput.class)); - _untouchables.add(new ClassKey(Response.class)); - } - - /** - * These are classes that we never use for reading - * (never try to deserialize instances of these types). - */ - public final static Class<?>[] _unreadableClasses = new Class<?>[] { - InputStream.class, Reader.class - }; - - /** - * These are classes that we never use for writing - * (never try to serialize instances of these types). - */ - public final static Class<?>[] _unwritableClasses = new Class<?>[] { - OutputStream.class, Writer.class, - StreamingOutput.class, Response.class - }; - - /* - /********************************************************** - /* Bit of caching - /********************************************************** - */ - - /** - * Cache for resolved endpoint configurations when reading XML - */ - protected final LRUMap<AnnotationBundleKey, XMLEndpointConfig> _readers - = new LRUMap<AnnotationBundleKey, XMLEndpointConfig>(16, 120); - - /** - * Cache for resolved endpoint configurations when writing XML - */ - protected final LRUMap<AnnotationBundleKey, XMLEndpointConfig> _writers - = new LRUMap<AnnotationBundleKey, XMLEndpointConfig>(16, 120); - - /* - /********************************************************** - /* General configuration - /********************************************************** - */ - - /** - * Helper object used for encapsulating configuration aspects - * of {@link XmlMapper} - */ - protected final XMLMapperConfigurator _mapperConfig; - - /** - * Set of types (classes) that provider should ignore for data binding - */ - protected HashSet<ClassKey> _cfgCustomUntouchables; /* /********************************************************** @@ -171,28 +79,6 @@ public class JacksonXMLProvider /* /********************************************************** - /* Configuration - /********************************************************** - */ - - /** - * Whether we want to actually check that Jackson has - * a serializer for given type. Since this should generally - * be the case (due to auto-discovery) and since the call - * to check availability can be bit expensive, defaults to false. - */ - protected boolean _cfgCheckCanSerialize = false; - - /** - * Whether we want to actually check that Jackson has - * a deserializer for given type. Since this should generally - * be the case (due to auto-discovery) and since the call - * to check availability can be bit expensive, defaults to false. - */ - protected boolean _cfgCheckCanDeserialize = false; - - /* - /********************************************************** /* Construction /********************************************************** */ @@ -201,8 +87,7 @@ public class JacksonXMLProvider * Default constructor, usually used when provider is automatically * configured to be used with JAX-RS implementation. */ - public JacksonXMLProvider() - { + public JacksonXMLProvider() { this(null, BASIC_ANNOTATIONS); } @@ -215,8 +100,7 @@ public class JacksonXMLProvider this(null, annotationsToUse); } - public JacksonXMLProvider(XmlMapper mapper) - { + public JacksonXMLProvider(XmlMapper mapper) { this(mapper, BASIC_ANNOTATIONS); } @@ -228,328 +112,42 @@ public class JacksonXMLProvider * @param annotationsToUse Sets of annotations (Jackson, JAXB) that provider should * support */ - public JacksonXMLProvider(XmlMapper mapper, Annotations[] annotationsToUse) - { - _mapperConfig = new XMLMapperConfigurator(mapper, annotationsToUse); + public JacksonXMLProvider(XmlMapper mapper, Annotations[] annotationsToUse) { + super(new XMLMapperConfigurator(mapper, annotationsToUse)); } /** * Method that will return version information stored in and read from jar * that contains this class. */ + @Override public Version version() { return PackageVersion.VERSION; } - - /* - /********************************************************** - /* Configuring - /********************************************************** - */ - - /** - * Method for defining whether actual detection for existence of - * a deserializer for type should be done when {@link #isReadable} - * is called. - */ - public void checkCanDeserialize(boolean state) { _cfgCheckCanDeserialize = state; } - - /** - * Method for defining whether actual detection for existence of - * a serializer for type should be done when {@link #isWriteable} - * is called. - */ - public void checkCanSerialize(boolean state) { _cfgCheckCanSerialize = state; } - - /** - * Method for configuring which annotation sets to use (including none). - * Annotation sets are defined in order decreasing precedence; that is, - * first one has the priority over following ones. - * - * @param annotationsToUse Ordered list of annotation sets to use; if null, - * default - */ - public void setAnnotationsToUse(Annotations[] annotationsToUse) { - _mapperConfig.setAnnotationsToUse(annotationsToUse); - } - - /** - * Method that can be used to directly define {@link XmlMapper} to use - * for serialization and deserialization; if null, will use the standard - * provider discovery from context instead. Default setting is null. - */ - public void setMapper(XmlMapper m) { - _mapperConfig.setMapper(m); - } - - public JacksonXMLProvider configure(DeserializationFeature f, boolean state) { - _mapperConfig.configure(f, state); - return this; - } - - public JacksonXMLProvider configure(SerializationFeature f, boolean state) { - _mapperConfig.configure(f, state); - return this; - } - - public JacksonXMLProvider configure(JsonParser.Feature f, boolean state) { - _mapperConfig.configure(f, state); - return this; - } - - public JacksonXMLProvider configure(JsonGenerator.Feature f, boolean state) { - _mapperConfig.configure(f, state); - return this; - } - public JacksonXMLProvider enable(DeserializationFeature f, boolean state) { - _mapperConfig.configure(f, true); - return this; - } - - public JacksonXMLProvider enable(SerializationFeature f, boolean state) { - _mapperConfig.configure(f, true); - return this; - } - - public JacksonXMLProvider enable(JsonParser.Feature f, boolean state) { - _mapperConfig.configure(f, true); - return this; - } - - public JacksonXMLProvider enable(JsonGenerator.Feature f, boolean state) { - _mapperConfig.configure(f, true); - return this; - } - - public JacksonXMLProvider disable(DeserializationFeature f, boolean state) { - _mapperConfig.configure(f, false); - return this; - } - - public JacksonXMLProvider disable(SerializationFeature f, boolean state) { - _mapperConfig.configure(f, false); - return this; - } - - public JacksonXMLProvider disable(JsonParser.Feature f, boolean state) { - _mapperConfig.configure(f, false); - return this; - } - - public JacksonXMLProvider disable(JsonGenerator.Feature f, boolean state) { - _mapperConfig.configure(f, false); - return this; - } - - /** - * Method for marking specified type as "untouchable", meaning that provider - * will not try to read or write values of this type (or its subtypes). - * - * @param type Type to consider untouchable; can be any kind of class, - * including abstract class or interface. No instance of this type - * (including subtypes, i.e. types assignable to this type) will - * be read or written by provider - */ - public void addUntouchable(Class<?> type) - { - if (_cfgCustomUntouchables == null) { - _cfgCustomUntouchables = new HashSet<ClassKey>(); - } - _cfgCustomUntouchables.add(new ClassKey(type)); - } - /* /********************************************************** - /* MessageBodyReader impl + /* Abstract method impls /********************************************************** */ - /** - * Method that JAX-RS container calls to try to check whether - * values of given type (and media type) can be deserialized by - * this provider. - * Implementation will first check that expected media type is - * an XML type (via call to {@link #isXMLType}; then verify - * that type is not one of "untouchable" types (types we will never - * automatically handle), and finally that there is a deserializer - * for type (iff {@link #checkCanDeserialize} has been called with - * true argument -- otherwise assumption is there will be a handler) - */ - public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) - { - if (!isXMLType(mediaType) || !isReadableType(type)) { - return false; - } - // if we really want to verify that we can serialize, we'll check: - if (_cfgCheckCanSerialize) { - XmlMapper mapper = locateMapper(type, mediaType); - if (!mapper.canDeserialize(mapper.constructType(type))) { - return false; - } - } - return true; - } - - /** - * Method that JAX-RS container calls to deserialize given value. - */ - public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,String> httpHeaders, InputStream entityStream) - throws IOException - { - AnnotationBundleKey key = new AnnotationBundleKey(annotations); - XMLEndpointConfig endpoint; - synchronized (_readers) { - endpoint = _readers.get(key); - } - // not yet resolved (or not cached any more)? Resolve! - if (endpoint == null) { - XmlMapper mapper = locateMapper(type, mediaType); - endpoint = XMLEndpointConfig.forReading(mapper, annotations); - // and cache for future reuse - synchronized (_readers) { - _readers.put(key.immutableKey(), endpoint); - } - } - ObjectReader reader = endpoint.getReader(); - // Fix for [Issue#4]: note, can not try to advance parser, XML parser complains - PushbackInputStream wrappedStream = new PushbackInputStream(entityStream); - int firstByte = wrappedStream.read(); - if (firstByte == -1) { - return null; - } - wrappedStream.unread(firstByte); - JsonParser jp = reader.getFactory().createParser(wrappedStream); - return reader.withType(genericType).readValue(jp); - } - - /* - /********************************************************** - /* MessageBodyWriter impl - /********************************************************** - */ - - /** - * Method that JAX-RS container calls to try to figure out - * serialized length of given value. Since computation of - * this length is about as expensive as serialization itself, - * implementation will return -1 to denote "not known", so - * that container will determine length from actual serialized - * output (if needed). - */ - public long getSize(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) - { - /* In general figuring output size requires actual writing; usually not - * worth it to write everything twice. - */ - return -1; + @Override + protected XMLEndpointConfig _configForReading(XmlMapper mapper, Annotation[] annotations) { + return XMLEndpointConfig.forReading(mapper, annotations); } - /** - * Method that JAX-RS container calls to try to check whether - * given value (of specified type) can be serialized by - * this provider. - * Implementation will first check that expected media type is - * an XML type (via call to {@link #isXMLType}; then verify - * that type is not one of "untouchable" types (types we will never - * automatically handle), and finally that there is a serializer - * for type (iff {@link #checkCanSerialize} has been called with - * true argument -- otherwise assumption is there will be a handler) - */ - public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) - { - if (!isXMLType(mediaType) || !isWritableType(type)) { - return false; - } - // Also: if we really want to verify that we can deserialize, we'll check: - if (_cfgCheckCanSerialize) { - if (!locateMapper(type, mediaType).canSerialize(type)) { - return false; - } - } - return true; + @Override + protected XMLEndpointConfig _configForWriting(XmlMapper mapper, Annotation[] annotations) { + return XMLEndpointConfig.forWriting(mapper, annotations); } - - /** - * Method that JAX-RS container calls to serialize given value. - */ - public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, - MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream) - throws IOException - { - AnnotationBundleKey key = new AnnotationBundleKey(annotations); - XMLEndpointConfig endpoint; - synchronized (_writers) { - endpoint = _writers.get(key); - } - // not yet resolved (or not cached any more)? Resolve! - if (endpoint == null) { - XmlMapper mapper = locateMapper(type, mediaType); - endpoint = XMLEndpointConfig.forWriting(mapper, annotations); - // and cache for future reuse - synchronized (_writers) { - _writers.put(key.immutableKey(), endpoint); - } - } - - ObjectWriter writer = endpoint.getWriter(); - - /* 27-Feb-2009, tatu: Where can we find desired encoding? Within - * HTTP headers? - */ - JsonEncoding enc = findEncoding(mediaType, httpHeaders); - JsonGenerator jg = writer.getFactory().createGenerator(entityStream, enc); - - // Want indentation? - if (writer.isEnabled(SerializationFeature.INDENT_OUTPUT)) { - jg.useDefaultPrettyPrinter(); - } - // 04-Mar-2010, tatu: How about type we were given? (if any) - JavaType rootType = null; - - if (genericType != null && value != null) { - /* 10-Jan-2011, tatu: as per [JACKSON-456], it's not safe to just force root - * type since it prevents polymorphic type serialization. Since we really - * just need this for generics, let's only use generic type if it's truly - * generic. - */ - if (genericType.getClass() != Class.class) { // generic types are other impls of 'java.lang.reflect.Type' - /* This is still not exactly right; should root type be further - * specialized with 'value.getClass()'? Let's see how well this works before - * trying to come up with more complete solution. - */ - rootType = writer.getTypeFactory().constructType(genericType); - /* 26-Feb-2011, tatu: To help with [JACKSON-518], we better recognize cases where - * type degenerates back into "Object.class" (as is the case with plain TypeVariable, - * for example), and not use that. - */ - if (rootType.getRawClass() == Object.class) { - rootType = null; - } - } - } - // Most of the configuration now handled through EndpointConfig, ObjectWriter - // but we may need to force root type: - if (rootType != null) { - writer = writer.withType(rootType); - } - writer.writeValue(jg, value); - } - + /** - * Helper method to use for determining desired output encoding. - * For now, will always just use UTF-8... + * @deprecated Since 2.2 use {@link #hasMatchingMediaType(MediaType)} instead */ - protected JsonEncoding findEncoding(MediaType mediaType, MultivaluedMap<String,Object> httpHeaders) - { - return JsonEncoding.UTF8; + @Deprecated + protected boolean isXMLType(MediaType mediaType) { + return hasMatchingMediaType(mediaType); } - - /* - /********************************************************** - /* Overridable helper methods - /********************************************************** - */ /** * Helper method used to check whether given media type @@ -558,7 +156,8 @@ public class JacksonXMLProvider * {@link MediaType#getSubtype} returns "xml" or something * ending with "+xml". */ - protected boolean isXMLType(MediaType mediaType) + @Override + protected boolean hasMatchingMediaType(MediaType mediaType) { /* As suggested by Stephen D, there are 2 ways to check: either * being as inclusive as possible (if subtype is "xml"), or @@ -576,57 +175,6 @@ public class JacksonXMLProvider */ return true; } - - /** - * Helper method called to see if given type is readable, that is, - * acceptable Java type to bind from XML - */ - protected boolean isReadableType(Class<?> type) - { - /* Ok: looks like we must weed out some core types here; ones that - * make no sense to try to bind from XML - */ - if (_untouchables.contains(new ClassKey(type))) { - return false; - } - // and there are some other abstract/interface types to exclude too: - for (Class<?> cls : _unreadableClasses) { - if (cls.isAssignableFrom(type)) { - return false; - } - } - // as well as possible custom exclusions - if (_containedIn(type, _cfgCustomUntouchables)) { - return false; - } - return true; - } - - - /** - * Helper method called to see if given type is writable, that is, - * acceptable Java type to write out as XML. - */ - protected boolean isWritableType(Class<?> type) - { - /* Ok: looks like we must weed out some core types here; ones that - * make no sense to try to write out as XML: - */ - if (_untouchables.contains(new ClassKey(type))) { - return false; - } - // but some are interface/abstract classes, so - for (Class<?> cls : _unwritableClasses) { - if (cls.isAssignableFrom(type)) { - return false; - } - } - // and finally, may have additional custom types to exclude - if (_containedIn(type, _cfgCustomUntouchables)) { - return false; - } - return true; - } /** * Method called to locate {@link XmlMapper} to use for serialization @@ -648,7 +196,8 @@ public class JacksonXMLProvider * not used by this method, * but will be passed to {@link ContextResolver} as is. */ - public XmlMapper locateMapper(Class<?> type, MediaType mediaType) + @Override + public XmlMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType) { // First: were we configured with a specific instance? XmlMapper m = _mapperConfig.getConfiguredMapper(); @@ -678,51 +227,21 @@ public class JacksonXMLProvider /* /********************************************************** - /* Private/sub-class helper methods + /* Overrides /********************************************************** */ - protected static boolean _containedIn(Class<?> mainType, HashSet<ClassKey> set) - { - if (set != null) { - ClassKey key = new ClassKey(mainType); - // First: type itself? - if (set.contains(key)) return true; - // Then supertypes (note: will not contain Object.class) - for (Class<?> cls : findSuperTypes(mainType, null)) { - key.reset(cls); - if (set.contains(key)) return true; - } - } - return false; - } - - private static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore) - { - return findSuperTypes(cls, endBefore, new ArrayList<Class<?>>(8)); - } - - private static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore, List<Class<?>> result) - { - _addSuperTypes(cls, endBefore, result, false); - return result; - } - - private static void _addSuperTypes(Class<?> cls, Class<?> endBefore, Collection<Class<?>> result, boolean addClassItself) + @Override + protected JsonParser _createParser(ObjectReader reader, InputStream rawStream) + throws IOException { - if (cls == endBefore || cls == null || cls == Object.class) { - return; - } - if (addClassItself) { - if (result.contains(cls)) { // already added, no need to check supers - return; - } - result.add(cls); - } - for (Class<?> intCls : cls.getInterfaces()) { - _addSuperTypes(intCls, endBefore, result, true); + // Fix for [Issue#4]: note, can not try to advance parser, XML parser complains + PushbackInputStream wrappedStream = new PushbackInputStream(rawStream); + int firstByte = wrappedStream.read(); + if (firstByte == -1) { + return null; } - _addSuperTypes(cls.getSuperclass(), endBefore, result, true); + wrappedStream.unread(firstByte); + return reader.getFactory().createParser(wrappedStream); } - } diff --git a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JsonMappingExceptionMapper.java b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JsonMappingExceptionMapper.java index 83c26eb..7a9316f 100644 --- a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JsonMappingExceptionMapper.java +++ b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JsonMappingExceptionMapper.java @@ -12,6 +12,7 @@ import javax.ws.rs.ext.Provider; */ @Provider public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> { + @Override public Response toResponse(JsonMappingException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); } diff --git a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JsonParseExceptionMapper.java b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JsonParseExceptionMapper.java index 784ea3a..1623924 100644 --- a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JsonParseExceptionMapper.java +++ b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/JsonParseExceptionMapper.java @@ -12,6 +12,7 @@ import javax.ws.rs.ext.Provider; */ @Provider public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> { + @Override public Response toResponse(JsonParseException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); } diff --git a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/XMLEndpointConfig.java b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/XMLEndpointConfig.java index ee23c35..32534eb 100644 --- a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/XMLEndpointConfig.java +++ b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/XMLEndpointConfig.java @@ -2,11 +2,9 @@ package com.fasterxml.jackson.jaxrs.xml; import java.lang.annotation.Annotation; -import com.fasterxml.jackson.annotation.*; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; + +import com.fasterxml.jackson.jaxrs.base.cfg.EndpointConfigBase; import com.fasterxml.jackson.jaxrs.xml.annotation.JacksonFeatures; /** @@ -14,27 +12,8 @@ import com.fasterxml.jackson.jaxrs.xml.annotation.JacksonFeatures; * for JAX-RS end points. */ public class XMLEndpointConfig + extends EndpointConfigBase<XMLEndpointConfig> { - // // General configuration - - protected Class<?> _activeView; - - protected String _rootName; - - // // Deserialization-only config - - protected DeserializationFeature[] _deserEnable; - protected DeserializationFeature[] _deserDisable; - - protected ObjectReader _reader; - - // // Serialization-only config - - protected SerializationFeature[] _serEnable; - protected SerializationFeature[] _serDisable; - - protected ObjectWriter _writer; - /* /********************************************************** /* Construction @@ -58,129 +37,28 @@ public class XMLEndpointConfig .initWriter(mapper) ; } - - protected XMLEndpointConfig add(Annotation[] annotations, boolean forWriting) + + @Override + protected void addAnnotation(Class<? extends Annotation> type, + Annotation annotation, boolean forWriting) { - // Same as [issue-10] with JSON provider; must check for null: - if (annotations != null) { - for (Annotation annotation : annotations) { - Class<?> type = annotation.annotationType(); - if (type == JsonView.class) { - // Can only use one view; but if multiple defined, use first (no exception) - Class<?>[] views = ((JsonView) annotation).value(); - _activeView = (views.length > 0) ? views[0] : null; - } else if (type == JsonRootName.class) { - _rootName = ((JsonRootName) annotation).value(); - } else if (type == JacksonFeatures.class) { - JacksonFeatures feats = (JacksonFeatures) annotation; - if (forWriting) { - _serEnable = nullIfEmpty(feats.serializationEnable()); - _serDisable = nullIfEmpty(feats.serializationDisable()); - } else { - _deserEnable = nullIfEmpty(feats.deserializationEnable()); - _deserDisable = nullIfEmpty(feats.deserializationDisable()); - } - } else if (type == JacksonAnnotationsInside.class) { - // skip; processed below (in parent), so encountering here is of no use + if (type == JacksonFeatures.class) { + JacksonFeatures feats = (JacksonFeatures) annotation; + if (forWriting) { + _serEnable = nullIfEmpty(feats.serializationEnable()); + _serDisable = nullIfEmpty(feats.serializationDisable()); } else { - // For all unrecognized types, check meta-annotation(s) to see if they are bundles - JacksonAnnotationsInside inside = type.getAnnotation(JacksonAnnotationsInside.class); - if (inside != null) { - add(type.getAnnotations(), forWriting); - } + _deserEnable = nullIfEmpty(feats.deserializationEnable()); + _deserDisable = nullIfEmpty(feats.deserializationDisable()); } - } - } - return this; - } - - protected XMLEndpointConfig initReader(ObjectMapper mapper) - { - // first common config - if (_activeView != null) { - _reader = mapper.readerWithView(_activeView); - } else { - _reader = mapper.reader(); - } - - if (_rootName != null) { - _reader = _reader.withRootName(_rootName); - } - // Then deser features - if (_deserEnable != null) { - _reader = _reader.withFeatures(_deserEnable); - } - if (_deserDisable != null) { - _reader = _reader.withoutFeatures(_deserDisable); - } - /* Important: we are NOT to close the underlying stream after - * mapping, so we need to instruct parser: - */ - _reader.getFactory().disable(JsonParser.Feature.AUTO_CLOSE_SOURCE); - - return this; - } - - protected XMLEndpointConfig initWriter(ObjectMapper mapper) - { - // first common config - if (_activeView != null) { - _writer = mapper.writerWithView(_activeView); } else { - _writer = mapper.writer(); - } - if (_rootName != null) { - _writer = _writer.withRootName(_rootName); - } - // Then features - if (_serEnable != null) { - _writer = _writer.withFeatures(_serEnable); - } - if (_serDisable != null) { - _writer = _writer.withoutFeatures(_serDisable); - } - // then others - - // Finally: couple of features we always set - - /* Important: we are NOT to close the underlying stream after - * mapping, so we need to instruct parser: - */ - _writer.getFactory().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); - - return this; - } - - /* - /********************************************************** - /* Accessors - /********************************************************** - */ - - public ObjectReader getReader() { - if (_reader == null) { // sanity check, should never happen - throw new IllegalStateException(); - } - return _reader; - } - - public ObjectWriter getWriter() { - if (_writer == null) { // sanity check, should never happen - throw new IllegalStateException(); + super.addAnnotation(type, annotation, forWriting); } - return _writer; } - /* - /********************************************************** - /* Helper methods - /********************************************************** - */ - - private static <T> T[] nullIfEmpty(T[] arg) { - if (arg == null || arg.length == 0) { - return null; - } - return arg; + @Override + public Object modifyBeforeWrite(Object value) { + // nothing to add + return value; } } diff --git a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/XMLMapperConfigurator.java b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/XMLMapperConfigurator.java index 3d5dbff..ee5cdce 100644 --- a/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/XMLMapperConfigurator.java +++ b/xml/src/main/java/com/fasterxml/jackson/jaxrs/xml/XMLMapperConfigurator.java @@ -34,6 +34,7 @@ public class XMLMapperConfigurator /** * Method that locates, configures and returns {@link XmlMapper} to use */ + @Override public synchronized XmlMapper getConfiguredMapper() { /* important: should NOT call mapper(); needs to return null * if no instance has been passed or constructed @@ -41,6 +42,7 @@ public class XMLMapperConfigurator return _mapper; } + @Override public synchronized XmlMapper getDefaultMapper() { if (_defaultMapper == null) { diff --git a/xml/src/test/java/com/fasterxml/jackson/jaxrs/xml/TestUntouchables.java b/xml/src/test/java/com/fasterxml/jackson/jaxrs/xml/TestUntouchables.java index dcad7c3..87aac96 100644 --- a/xml/src/test/java/com/fasterxml/jackson/jaxrs/xml/TestUntouchables.java +++ b/xml/src/test/java/com/fasterxml/jackson/jaxrs/xml/TestUntouchables.java @@ -23,7 +23,7 @@ public class TestUntouchables // Some users of JacksonJsonProvider override this method; // changing to "private" would regress them. @Override - protected boolean isXMLType(MediaType mediaType) { return super.isXMLType(mediaType); } + protected boolean hasMatchingMediaType(MediaType mediaType) { return super.hasMatchingMediaType(mediaType); } } /* -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jackson-jaxrs-providers.git _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

