package org.deephacks.confit.internal.jaxrs; import org.codehaus.jackson.Version; import org.codehaus.jackson.annotate.JsonAutoDetect; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.JsonDeserializer; import org.codehaus.jackson.map.JsonSerializer; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.introspect.VisibilityChecker; import org.codehaus.jackson.map.module.SimpleModule; import org.deephacks.confit.model.ClassLoaderHolder; import org.deephacks.confit.spi.Lookup; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class JaxrsObjects { private Collection<JaxrsObject> objects = new ArrayList<>(); private long totalCount; public JaxrsObjects() { } public JaxrsObjects(Collection<?> objects) { addAll(objects); } public void add(JaxrsObject object) { this.objects.add(object); } public void addAll(Collection<?> objects) { for (Object object : objects) { add(new JaxrsObject(object)); } } public void setTotalCount(long total) { this.totalCount = total; } public long getTotalCount() { return totalCount; } public Collection<JaxrsObject> getObjects() { return objects; } public Collection<Object> toObjects() { ArrayList<Object> objects = new ArrayList<>(); for (JaxrsObject jaxrsObject : this.objects) { objects.add(jaxrsObject.toObject()); } return objects; } public static class JaxrsObject { private static final ObjectMapper mapper = new ObjectMapper(); static { mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setVisibilityChecker(VisibilityChecker.Std.defaultInstance() .withFieldVisibility(JsonAutoDetect.Visibility.ANY)); // register jackson serializers/deserilzers for custom simple data types // using standard java service provider lookup. SimpleModule module = new SimpleModule("confit", new Version(1, 0, 0, null)); Collection<JsonDeserializer> deserializers = Lookup.get().lookupAll(JsonDeserializer.class); for (JsonDeserializer deserializer : deserializers) { List<Class<?>> cls = getParameterizedType(deserializer.getClass(), deserializer.getClass()); module.addDeserializer(cls.get(0), deserializer); } Collection<JsonSerializer> serializers = Lookup.get().lookupAll(JsonSerializer.class); for (JsonSerializer serializer : serializers) { List<Class<?>> cls = getParameterizedType(serializer.getClass(), serializer.getClass()); module.addSerializer(cls.get(0), serializer); } mapper.registerModule(module); } private String className; private Object object; public JaxrsObject() { } public JaxrsObject(String className, Object object) { this.className = className; this.object = object; } public JaxrsObject(Object o) { this.className = o.getClass().getName(); this.object = o; } public void setClassName(String className) { this.className = className; } public String getClassName() { return className; } public Object getObject(){ return object; } public Object toObject() { try { Class<?> clazz = Class.forName(className, true, ClassLoaderHolder.getClassLoader()); Object value = mapper.convertValue(object, clazz); if (value == null) { return clazz.newInstance(); } return value; } catch (Exception e) { throw new RuntimeException(e); } } } private static List<Class<?>> getParameterizedType(final Class<?> ownerClass, Class<?> genericSuperClass) { Type[] types = null; if (genericSuperClass.isInterface()) { types = ownerClass.getGenericInterfaces(); } else { types = new Type[] { ownerClass.getGenericSuperclass() }; } List<Class<?>> classes = new ArrayList<>(); for (Type type : types) { if (!ParameterizedType.class.isAssignableFrom(type.getClass())) { // the field is it a raw type and does not have generic type // argument. Return empty list. return new ArrayList<Class<?>>(); } ParameterizedType ptype = (ParameterizedType) type; Type[] targs = ptype.getActualTypeArguments(); for (Type aType : targs) { classes.add(extractClass(ownerClass, aType)); } } return classes; } private static Class<?> extractClass(Class<?> ownerClass, Type arg) { if (arg instanceof ParameterizedType) { return extractClass(ownerClass, ((ParameterizedType) arg).getRawType()); } else if (arg instanceof GenericArrayType) { throw new UnsupportedOperationException("GenericArray types are not supported."); } else if (arg instanceof TypeVariable) { throw new UnsupportedOperationException("GenericArray types are not supported."); } return (arg instanceof Class ? (Class<?>) arg : Object.class); } }