From 3892c78dcb76d6fbc6ff79c78b3c2cae8da7db14 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 16 Mar 2013 21:12:59 -0700 Subject: [PATCH] Add unit tests for #5 --- .../jackson/jaxrs/base/ProviderBase.java | 107 ++++++++++++------ .../jaxrs/json/annotation/package-info.java | 3 +- .../jackson/jaxrs/json/TestUntouchables.java | 19 ++++ release-notes/VERSION | 1 + 4 files changed, 91 insertions(+), 39 deletions(-) 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 a31eccb3..46361c54 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 @@ -3,10 +3,7 @@ import java.io.*; import java.lang.annotation.Annotation; import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; +import java.util.*; import javax.ws.rs.core.*; import javax.ws.rs.ext.MessageBodyReader; @@ -16,10 +13,7 @@ import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.util.LRUMap; -import com.fasterxml.jackson.jaxrs.cfg.AnnotationBundleKey; -import com.fasterxml.jackson.jaxrs.cfg.Annotations; -import com.fasterxml.jackson.jaxrs.cfg.EndpointConfigBase; -import com.fasterxml.jackson.jaxrs.cfg.MapperConfiguratorBase; +import com.fasterxml.jackson.jaxrs.cfg.*; import com.fasterxml.jackson.jaxrs.util.ClassKey; public abstract class ProviderBase< @@ -88,9 +82,11 @@ public abstract class ProviderBase< */ /** - * Set of types (classes) that provider should ignore for data binding + * Map that contains overrides to default list of untouchable + * types: true meaning that entry is untouchable, + * false that is is not. */ - protected HashSet _cfgCustomUntouchables; + protected HashMap _cfgCustomUntouchables; /** * Whether we want to actually check that Jackson has @@ -186,11 +182,25 @@ protected ProviderBase(MAPPER_CONFIG mconfig) { public void addUntouchable(Class type) { if (_cfgCustomUntouchables == null) { - _cfgCustomUntouchables = new HashSet(); + _cfgCustomUntouchables = new HashMap(); } - _cfgCustomUntouchables.add(new ClassKey(type)); + _cfgCustomUntouchables.put(new ClassKey(type), Boolean.TRUE); } + /** + * Method for removing definition of specified type as untouchable: + * usually only + * + * @since 2.2 + */ + public void removeUntouchable(Class type) + { + if (_cfgCustomUntouchables == null) { + _cfgCustomUntouchables = new HashMap(); + } + _cfgCustomUntouchables.put(new ClassKey(type), Boolean.FALSE); + } + /** * Method for configuring which annotation sets to use (including none). * Annotation sets are defined in order decreasing precedence; that is, @@ -336,23 +346,24 @@ public boolean isWriteable(Class type, Type genericType, Annotation[] annotat return false; } - /* Ok: looks like we must weed out some core types here; ones that - * make no sense to try to bind from JSON: - */ - if (_untouchables.contains(new ClassKey(type))) { + Boolean customUntouchable = _findCustomUntouchable(type); + if (customUntouchable == Boolean.TRUE) { return false; } - // but some are interface/abstract classes, so - for (Class cls : _unwritableClasses) { - if (cls.isAssignableFrom(type)) { + if (customUntouchable == null) { + /* Ok: looks like we must weed out some core types here; ones that + * make no sense to try to bind from JSON: + */ + 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; - } - // Also: if we really want to verify that we can deserialize, we'll check: if (_cfgCheckCanSerialize) { if (!locateMapper(type, mediaType).canSerialize(type)) { @@ -463,23 +474,24 @@ public boolean isReadable(Class type, Type genericType, Annotation[] annotati return false; } - /* Ok: looks like we must weed out some core types here; ones that - * make no sense to try to bind from JSON: - */ - if (_untouchables.contains(new ClassKey(type))) { + Boolean customUntouchable = _findCustomUntouchable(type); + if (customUntouchable == Boolean.TRUE) { return false; } - // and there are some other abstract/interface types to exclude too: - for (Class cls : _unreadableClasses) { - if (cls.isAssignableFrom(type)) { + if (customUntouchable == null) { + /* Ok: looks like we must weed out some core types here; ones that + * make no sense to try to bind from JSON: + */ + 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; - } - // Finally: if we really want to verify that we can serialize, we'll check: if (_cfgCheckCanSerialize) { ObjectMapper mapper = locateMapper(type, mediaType); @@ -572,7 +584,7 @@ public MAPPER locateMapper(Class type, MediaType mediaType) } return m; } - + protected static boolean _containedIn(Class mainType, HashSet set) { if (set != null) { @@ -588,6 +600,27 @@ protected static boolean _containedIn(Class mainType, HashSet set) return false; } + protected Boolean _findCustomUntouchable(Class mainType) + { + if (_cfgCustomUntouchables != null) { + ClassKey key = new ClassKey(mainType); + // First: type itself? + Boolean b = _cfgCustomUntouchables.get(key); + if (b != null) { + return b; + } + // Then supertypes (note: will not contain Object.class) + for (Class cls : findSuperTypes(mainType, null)) { + key.reset(cls); + b = _cfgCustomUntouchables.get(key); + if (b != null) { + return b; + } + } + } + return null; + } + protected static List> findSuperTypes(Class cls, Class endBefore) { return findSuperTypes(cls, endBefore, new ArrayList>(8)); diff --git a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/annotation/package-info.java b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/annotation/package-info.java index c386bf48..8b1e12cc 100644 --- a/json/src/main/java/com/fasterxml/jackson/jaxrs/json/annotation/package-info.java +++ b/json/src/main/java/com/fasterxml/jackson/jaxrs/json/annotation/package-info.java @@ -1,6 +1,5 @@ /** - * Package that contains utility classes and methods for - * the JAX-RS JSON provider module. + * Package that contains annotations specific to JSON dataformat. *

* NOTE: starting with version 2.2, general-purpose annotations * will be moved to a shared package, and this package will only 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 ab741bf8..9ed8012a 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 @@ -76,6 +76,25 @@ public void testCustomUntouchables() throws Exception new Annotation[0], MediaType.APPLICATION_JSON_TYPE)); assertFalse(prov.isWriteable(HashSet.class, HashSet.class, new Annotation[0], MediaType.APPLICATION_JSON_TYPE)); + + // But also allow removals... + prov.removeUntouchable(Collection.class); + assertTrue(prov.isReadable(ArrayList.class, ArrayList.class, + new Annotation[0], MediaType.APPLICATION_JSON_TYPE)); + assertTrue(prov.isWriteable(HashSet.class, HashSet.class, + new Annotation[0], MediaType.APPLICATION_JSON_TYPE)); + // which should even override default ones + + assertFalse(prov.isReadable(String.class, getClass(), + new Annotation[0], MediaType.APPLICATION_JSON_TYPE)); + assertFalse(prov.isWriteable(String.class, HashSet.class, + new Annotation[0], MediaType.APPLICATION_JSON_TYPE)); + prov.removeUntouchable(String.class); + assertTrue(prov.isReadable(String.class, getClass(), + new Annotation[0], MediaType.APPLICATION_JSON_TYPE)); + assertTrue(prov.isWriteable(String.class, HashSet.class, + new Annotation[0], MediaType.APPLICATION_JSON_TYPE)); + } } \ No newline at end of file diff --git a/release-notes/VERSION b/release-notes/VERSION index 98e71fe4..74870f7b 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -9,6 +9,7 @@ First multi-module release, to make release easier, share some boilerplate code. Changes: +#5: Add 'provider.removeUntouchable()' * Add Woodstox dependency (not just in 'test' scope) to try to avoid problems with users relying on SJSXP (such as 'extra' xmlns declarations)