From fe2e05c459b4a329194ab8ec7dff3ecdb627d155 Mon Sep 17 00:00:00 2001 From: pkupczyk <pkupczyk> Date: Tue, 5 Jun 2012 09:41:39 +0000 Subject: [PATCH] SP-82 BIS-14 Query Plugins: improve the JSON-RPC implementation to also accept custom classes and not only primitive types and collections SVN: 25560 --- .../JsonContainerDeserializer.java | 26 ++++++++-- .../server/json/JsonDeserializationTest.java | 49 ++++++++++++++++++- .../api/server/json/JsonTestObjectMapper.java | 2 + .../json/object/ObjectWithPrivateAccess.java | 46 +++++++++++++++++ 4 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java diff --git a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/deserializer/JsonContainerDeserializer.java b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/deserializer/JsonContainerDeserializer.java index a70747e1ced..d8eeae2e3ad 100644 --- a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/deserializer/JsonContainerDeserializer.java +++ b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/deserializer/JsonContainerDeserializer.java @@ -17,6 +17,8 @@ package ch.systemsx.cisd.common.api.server.json.deserializer; import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; @@ -36,6 +38,8 @@ import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.deser.BeanDeserializer; import org.codehaus.jackson.map.deser.BeanDeserializerFactory; import org.codehaus.jackson.map.deser.SettableBeanProperty; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.util.ClassUtil; import org.codehaus.jackson.type.JavaType; import ch.systemsx.cisd.common.api.server.json.common.JsonConstants; @@ -229,7 +233,7 @@ public class JsonContainerDeserializer extends JsonDeserializer<Object> try { - Object instance = tryCreateInstance(clazz); + Object instance = tryCreateInstance(clazz, ctxt); Iterator<SettableBeanProperty> properties = tryGetProperties(clazz, ctxt); if (properties != null) @@ -276,17 +280,29 @@ public class JsonContainerDeserializer extends JsonDeserializer<Object> return clazz; } - private Object tryCreateInstance(Class<?> clazz) throws IOException + private Object tryCreateInstance(Class<?> clazz, DeserializationContext ctxt) + throws IOException { try { - return clazz.newInstance(); + JavaType type = ctxt.getConfig().getTypeFactory().constructType(clazz); + BasicBeanDescription beanDesc = ctxt.getConfig().introspect(type); + Constructor<?> defaultConstructor = beanDesc.findDefaultConstructor(); + ClassUtil.checkAndFixAccess(defaultConstructor); + return defaultConstructor.newInstance(); + } catch (InstantiationException e) { - return new JsonMappingException("Couldn't create an instance of class: " + clazz, e); + throw new JsonMappingException("Couldn't create an instance of class: " + clazz, e); } catch (IllegalAccessException e) { - return new JsonMappingException("Couldn't create an instance of class: " + clazz, e); + throw new JsonMappingException("Couldn't create an instance of class: " + clazz, e); + } catch (IllegalArgumentException e) + { + throw new JsonMappingException("Couldn't create an instance of class: " + clazz, e); + } catch (InvocationTargetException e) + { + throw new JsonMappingException("Couldn't create an instance of class: " + clazz, e); } } diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java index 72684d2f845..6e8aaa34c50 100644 --- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java +++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java @@ -39,6 +39,7 @@ import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNested; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNestedChild; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrimitiveTypes; +import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrivateAccess; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithRenamedProperties; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithType; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeA; @@ -209,6 +210,13 @@ public class JsonDeserializationTest testDeserializeObjectWithRenamedProperties("@class", ".LegacyObjectWithRenamedProperties"); } + @Test + public void testDeserializeJsonWithPrivateAccess() throws Exception + { + testDeserializeObjectWithPrivateAccess("@type", "ObjectWithPrivateAccess"); + testDeserializeObjectWithPrivateAccess("@class", ".LegacyObjectWithPrivateAccess"); + } + @Test(expectedExceptions = JsonMappingException.class) public void testDeserializeJsonWithoutTypeToPolymorphicType() throws Exception { @@ -480,6 +488,23 @@ public class JsonDeserializationTest Assert.assertEquals(object.getY(), "propertyWithGetterAndSetterRenamedValue"); } + private void testDeserializeObjectWithPrivateAccess(String typeField, String typeValue) + throws Exception + { + Map<String, Object> objectMap = new HashMap<String, Object>(); + if (typeField != null && typeValue != null) + { + objectMap.put(typeField, typeValue); + } + + objectMap.put("field", "fieldValue"); + + ObjectWithPrivateAccess object = deserialize(objectMap, ObjectWithPrivateAccess.class); + + Assert.assertNotNull(object); + Assert.assertEquals(object.getField(), "fieldValue"); + } + private void testDeserializeObjectWithPrimitiveTypes(String typeField, String typeValue) throws Exception { @@ -682,6 +707,14 @@ public class JsonDeserializationTest return itemWithUnknownClass; } + private Map<String, Object> createItemWithPrivateAccess() + { + Map<String, Object> itemWithPrivateAccess = new HashMap<String, Object>(); + itemWithPrivateAccess.put("@class", ".LegacyObjectWithPrivateAccess"); + itemWithPrivateAccess.put("field", "itemWithPrivateAccess_field"); + return itemWithPrivateAccess; + } + @SuppressWarnings( { "rawtypes", "unchecked" }) private void assertItemWithUnknownClass(Object object) @@ -690,6 +723,13 @@ public class JsonDeserializationTest Assert.assertEquals(new HashMap((Map) object), createItemWithUnknownClass()); } + private void assertItemWithPrivateAccess(Object object) + { + Assert.assertEquals(object.getClass(), ObjectWithPrivateAccess.class); + ObjectWithPrivateAccess itemWithPrivateAccess = (ObjectWithPrivateAccess) object; + Assert.assertEquals("itemWithPrivateAccess_field", itemWithPrivateAccess.getField()); + } + @SuppressWarnings( { "rawtypes", "unchecked" }) private Map<String, Object> createObjectWithContainerTypes() @@ -700,6 +740,7 @@ public class JsonDeserializationTest collection.add(createItemWithKnownButNotUniqueClass()); collection.add(createItemWithUnknownType()); collection.add(createItemWithUnknownClass()); + collection.add(createItemWithPrivateAccess()); Map map = new HashMap(); map.put("itemWithKnownType", createItemWithKnownType()); @@ -707,6 +748,7 @@ public class JsonDeserializationTest map.put("itemWithKnownButNotUniqueClass", createItemWithKnownButNotUniqueClass()); map.put("itemWithUnknownType", createItemWithUnknownType()); map.put("itemWithUnknownClass", createItemWithUnknownClass()); + map.put("itemWithPrivateAccess", createItemWithPrivateAccess()); List list = new ArrayList(); list.add(createItemWithKnownType()); @@ -714,6 +756,7 @@ public class JsonDeserializationTest list.add(createItemWithKnownButNotUniqueClass()); list.add(createItemWithUnknownType()); list.add(createItemWithUnknownClass()); + list.add(createItemWithPrivateAccess()); Map<String, Object> object = new HashMap<String, Object>(); @@ -752,25 +795,27 @@ public class JsonDeserializationTest { "rawtypes" }) private void assertItemsCollection(Collection collection) { - Assert.assertEquals(collection.size(), 5); + Assert.assertEquals(collection.size(), 6); Iterator iterator = collection.iterator(); assertItemWithKnownType(iterator.next()); assertItemWithKnownUniqueClass(iterator.next()); assertItemWithKnownButNotUniqueClass(iterator.next()); assertItemWithUnknownType(iterator.next()); assertItemWithUnknownClass(iterator.next()); + assertItemWithPrivateAccess(iterator.next()); } @SuppressWarnings( { "rawtypes" }) private void assertItemsMap(Map map) { - Assert.assertEquals(map.size(), 5); + Assert.assertEquals(map.size(), 6); assertItemWithKnownType(map.get("itemWithKnownType")); assertItemWithKnownUniqueClass(map.get("itemWithKnownUniqueClass")); assertItemWithKnownButNotUniqueClass(map.get("itemWithKnownButNotUniqueClass")); assertItemWithUnknownType(map.get("itemWithUnknownType")); assertItemWithUnknownClass(map.get("itemWithUnknownClass")); + assertItemWithPrivateAccess(map.get("itemWithPrivateAccess")); } @SuppressWarnings("unchecked") diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java index ea1502a0c33..d562c2a3f51 100644 --- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java +++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java @@ -30,6 +30,7 @@ import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNested; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNestedChild; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrimitiveTypes; +import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrivateAccess; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithRenamedProperties; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithType; import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeA; @@ -75,6 +76,7 @@ public class JsonTestObjectMapper extends ObjectMapper ObjectWithIgnoredProperties.class); classMapping.addClass(".LegacyObjectWithRenamedProperties", ObjectWithRenamedProperties.class); + classMapping.addClass(".LegacyObjectWithPrivateAccess", ObjectWithPrivateAccess.class); setAnnotationIntrospector(new JsonTypeAndClassAnnotationIntrospector(classMapping)); setSubtypeResolver(new JsonReflectionsSubTypeResolver(subTypesMapping)); diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java new file mode 100644 index 00000000000..6eaad338c61 --- /dev/null +++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java @@ -0,0 +1,46 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.api.server.json.object; + +import ch.systemsx.cisd.base.annotation.JsonObject; + +/** + * @author pkupczyk + */ + +@JsonObject("ObjectWithPrivateAccess") +public class ObjectWithPrivateAccess +{ + + private String field; + + private ObjectWithPrivateAccess() + { + } + + public String getField() + { + return field; + } + + @SuppressWarnings("unused") + private void setField(String field) + { + this.field = field; + } + +} -- GitLab