Skip to content

Commit

Permalink
Add unit tests for #5
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Mar 17, 2013
1 parent c200d91 commit 3892c78
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 39 deletions.
107 changes: 70 additions & 37 deletions base/src/main/java/com/fasterxml/jackson/jaxrs/base/ProviderBase.java
Expand Up @@ -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;
Expand All @@ -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<
Expand Down Expand Up @@ -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: <code>true</code> meaning that entry is untouchable,
* <code>false</code> that is is not.
*/
protected HashSet<ClassKey> _cfgCustomUntouchables;
protected HashMap<ClassKey,Boolean> _cfgCustomUntouchables;

/**
* Whether we want to actually check that Jackson has
Expand Down Expand Up @@ -186,11 +182,25 @@ protected ProviderBase(MAPPER_CONFIG mconfig) {
public void addUntouchable(Class<?> type)
{
if (_cfgCustomUntouchables == null) {
_cfgCustomUntouchables = new HashSet<ClassKey>();
_cfgCustomUntouchables = new HashMap<ClassKey,Boolean>();
}
_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<ClassKey,Boolean>();
}
_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,
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -572,7 +584,7 @@ public MAPPER locateMapper(Class<?> type, MediaType mediaType)
}
return m;
}

protected static boolean _containedIn(Class<?> mainType, HashSet<ClassKey> set)
{
if (set != null) {
Expand All @@ -588,6 +600,27 @@ protected static boolean _containedIn(Class<?> mainType, HashSet<ClassKey> 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<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore)
{
return findSuperTypes(cls, endBefore, new ArrayList<Class<?>>(8));
Expand Down
@@ -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.
*<p>
* NOTE: starting with version 2.2, general-purpose annotations
* will be moved to a shared package, and this package will only
Expand Down
Expand Up @@ -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));

}
}

1 change: 1 addition & 0 deletions release-notes/VERSION
Expand Up @@ -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)

Expand Down

0 comments on commit 3892c78

Please sign in to comment.