From: Mathieu Baudier Date: Fri, 18 Sep 2009 15:06:13 +0000 (+0000) Subject: Progress on JSON X-Git-Tag: argeo-commons-2.1.30~1787 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=00ae7654c948e62c35ef88e7d8d528965d5e0371 Progress on JSON git-svn-id: https://svn.argeo.org/commons/trunk@2966 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/security/demo/org.argeo.security.demo.log4j/log4j.properties b/security/demo/org.argeo.security.demo.log4j/log4j.properties index c9d2a9118..f54a84e41 100644 --- a/security/demo/org.argeo.security.demo.log4j/log4j.properties +++ b/security/demo/org.argeo.security.demo.log4j/log4j.properties @@ -8,7 +8,7 @@ log4j.logger.org.hibernate=WARN log4j.logger.org.springframework=WARN #log4j.logger.org.springframework.web=DEBUG #log4j.logger.org.springframework.jms=WARN -log4j.logger.org.springframework.security=DEBUG +log4j.logger.org.springframework.security=WARN log4j.org.apache.directory=ERROR diff --git a/security/demo/pom.xml b/security/demo/pom.xml index 8c9dfe992..bc46b0d36 100644 --- a/security/demo/pom.xml +++ b/security/demo/pom.xml @@ -34,6 +34,7 @@ org.argeo.security.manager.ldap, org.argeo.security.webapp, org.argeo.security.ria, + org.argeo.security.core, org.argeo.server.ads.server diff --git a/security/modules/.classpath b/security/modules/.classpath new file mode 100644 index 000000000..d0bec0f76 --- /dev/null +++ b/security/modules/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/security/modules/.project b/security/modules/.project new file mode 100644 index 000000000..c47b78c55 --- /dev/null +++ b/security/modules/.project @@ -0,0 +1,23 @@ + + + org.argeo.security.modules + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.maven.ide.eclipse.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/security/modules/.settings/org.eclipse.jdt.core.prefs b/security/modules/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..7d2259791 --- /dev/null +++ b/security/modules/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Fri Sep 18 15:22:32 CEST 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/security/modules/.settings/org.maven.ide.eclipse.prefs b/security/modules/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..3a44ef128 --- /dev/null +++ b/security/modules/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Fri Sep 18 15:22:23 CEST 2009 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/security/modules/org.argeo.security.webapp/META-INF/MANIFEST.MF b/security/modules/org.argeo.security.webapp/META-INF/MANIFEST.MF index 35682dd8e..74c67491f 100644 --- a/security/modules/org.argeo.security.webapp/META-INF/MANIFEST.MF +++ b/security/modules/org.argeo.security.webapp/META-INF/MANIFEST.MF @@ -3,6 +3,7 @@ Bundle-Version: 0.1.1.SNAPSHOT Import-Package: javax.servlet, javax.servlet.http, javax.servlet.resources, + org.argeo.security, org.argeo.security.dao, org.argeo.security.mvc, org.argeo.server.json, diff --git a/security/modules/org.argeo.security.webapp/WEB-INF/osgi.xml b/security/modules/org.argeo.security.webapp/WEB-INF/osgi.xml index 22cec14a5..aa2f7164a 100644 --- a/security/modules/org.argeo.security.webapp/WEB-INF/osgi.xml +++ b/security/modules/org.argeo.security.webapp/WEB-INF/osgi.xml @@ -12,4 +12,6 @@ + \ No newline at end of file diff --git a/security/modules/org.argeo.security.webapp/WEB-INF/security-servlet.xml b/security/modules/org.argeo.security.webapp/WEB-INF/security-servlet.xml index b2938510a..97d3b121a 100644 --- a/security/modules/org.argeo.security.webapp/WEB-INF/security-servlet.xml +++ b/security/modules/org.argeo.security.webapp/WEB-INF/security-servlet.xml @@ -12,6 +12,20 @@ + + + + + + + + + + + + + + diff --git a/security/modules/pom.xml b/security/modules/pom.xml index fb9ed5759..ff5031d4d 100644 --- a/security/modules/pom.xml +++ b/security/modules/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 org.argeo.commons @@ -22,4 +23,53 @@ + + + + org.argeo.commons.security + org.argeo.security.mvc + 0.1.1-SNAPSHOT + + + org.argeo.commons.security + org.argeo.security.ria + 0.1.1-SNAPSHOT + + + org.argeo.commons.server + org.argeo.server.json + 0.1.1-SNAPSHOT + + + + + org.argeo.commons.osgi + org.argeo.osgi.boot + 0.1.1-SNAPSHOT + + + + + org.argeo.commons.server + org.argeo.server.dep.tomcat + 0.1.1-SNAPSHOT + pom + + + org.argeo.commons.server + org.argeo.server.dep.ads + 0.1.1-SNAPSHOT + pom + + + + + org.springframework.osgi + org.springframework.osgi.extender + + + org.springframework.osgi + org.springframework.osgi.web.extender + + \ No newline at end of file diff --git a/security/runtime/org.argeo.security.core/.classpath b/security/runtime/org.argeo.security.core/.classpath index bab5b6519..98f38b674 100644 --- a/security/runtime/org.argeo.security.core/.classpath +++ b/security/runtime/org.argeo.security.core/.classpath @@ -1,7 +1,8 @@ - + + diff --git a/security/runtime/org.argeo.security.core/pom.xml b/security/runtime/org.argeo.security.core/pom.xml index 753d5d711..3fd7ae889 100644 --- a/security/runtime/org.argeo.security.core/pom.xml +++ b/security/runtime/org.argeo.security.core/pom.xml @@ -32,6 +32,9 @@ org.argeo.security.* + *, + org.argeo.server.json;resolution:=optional + diff --git a/security/runtime/org.argeo.security.core/src/main/resources/META-INF/spring/natures.xml b/security/runtime/org.argeo.security.core/src/main/resources/META-INF/spring/natures.xml new file mode 100644 index 000000000..b2ac1178b --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/resources/META-INF/spring/natures.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/security/runtime/org.argeo.security.core/src/main/resources/META-INF/spring/osgi.xml b/security/runtime/org.argeo.security.core/src/main/resources/META-INF/spring/osgi.xml new file mode 100644 index 000000000..649157f68 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/resources/META-INF/spring/osgi.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java index 4b91075ce..c95d90984 100644 --- a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java +++ b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java @@ -1,26 +1,47 @@ package org.argeo.security.mvc; +import java.io.Reader; +import java.io.StringReader; import java.util.List; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.security.ArgeoUser; +import org.argeo.security.BasicArgeoUser; import org.argeo.security.core.ArgeoUserDetails; import org.argeo.security.dao.RoleDao; import org.argeo.security.dao.UserDao; import org.argeo.server.BooleanAnswer; +import org.argeo.server.DeserializingEditor; import org.argeo.server.ServerAnswer; +import org.argeo.server.ServerDeserializer; import org.argeo.server.mvc.MvcConstants; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class UsersRolesController implements MvcConstants { + private final static Log log = LogFactory + .getLog(UsersRolesController.class); + private UserDao userDao; private RoleDao roleDao; + private ServerDeserializer userDeserializer = null; + + @InitBinder + public void initBinder(WebDataBinder binder) { + binder.registerCustomEditor(BasicArgeoUser.class, + new DeserializingEditor(userDeserializer)); + } + /* USER */ @RequestMapping("/getCredentials.security") @@ -43,6 +64,38 @@ public class UsersRolesController implements MvcConstants { return new BooleanAnswer(userDao.userExists(username)); } + @RequestMapping("/createUser.security") + @ModelAttribute(ANSWER_MODEL_KEY) + public ServerAnswer createUser(Reader reader) { + ArgeoUser user = (ArgeoUser) userDeserializer.deserialize(reader); + userDao.create(user); + return ServerAnswer.ok("User " + user.getUsername() + " created"); + } + + @RequestMapping("/updateUser.security") + @ModelAttribute(ANSWER_MODEL_KEY) + public ServerAnswer updateUser(Reader reader) { + ArgeoUser user = (ArgeoUser) userDeserializer.deserialize(reader); + userDao.update(user); + return ServerAnswer.ok("User " + user.getUsername() + " updated"); + } + + @RequestMapping("/createUser2.security") + @ModelAttribute(ANSWER_MODEL_KEY) + public ServerAnswer createUser(@RequestParam("body") String body) { + if (log.isDebugEnabled()) + log.debug("body:\n" + body); + StringReader reader = new StringReader(body); + ArgeoUser user = null; + try { + user = (ArgeoUser) userDeserializer.deserialize(reader); + } finally { + IOUtils.closeQuietly(reader); + } + userDao.create(user); + return ServerAnswer.ok("User " + user.getUsername() + " created"); + } + @RequestMapping("/deleteUser.security") @ModelAttribute(ANSWER_MODEL_KEY) public ServerAnswer deleteUser(@RequestParam("username") String username) { @@ -85,4 +138,8 @@ public class UsersRolesController implements MvcConstants { this.roleDao = roleDao; } + public void setUserDeserializer(ServerDeserializer userDeserializer) { + this.userDeserializer = userDeserializer; + } + } diff --git a/server/runtime/org.argeo.server.core/pom.xml b/server/runtime/org.argeo.server.core/pom.xml index 51d1267b4..89c480ddb 100644 --- a/server/runtime/org.argeo.server.core/pom.xml +++ b/server/runtime/org.argeo.server.core/pom.xml @@ -56,5 +56,11 @@ com.springsource.javax.servlet + + + org.slf4j + com.springsource.slf4j.org.apache.commons.logging + + diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java new file mode 100644 index 000000000..4c8dc6d8d --- /dev/null +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java @@ -0,0 +1,26 @@ +package org.argeo.server; + +import java.beans.PropertyEditorSupport; +import java.io.StringReader; + +import org.apache.commons.io.IOUtils; + +public class DeserializingEditor extends PropertyEditorSupport { + private ServerDeserializer deserializer; + + public DeserializingEditor(ServerDeserializer deserializer) { + super(); + this.deserializer = deserializer; + } + + @Override + public void setAsText(String text) throws IllegalArgumentException { + StringReader reader = new StringReader(text); + try { + setValue(deserializer.deserialize(reader)); + } finally { + IOUtils.closeQuietly(reader); + } + } + +} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java index c3e747608..9bf2634ae 100644 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java @@ -69,4 +69,9 @@ public class ServerAnswer { return new ServerAnswer(OK, message); } + @Override + public String toString() { + return "ServerAnswer{status:"+status+", message:"+message+"}"; + } + } diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerDeserializer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerDeserializer.java index 98b7f71eb..7c15b066c 100644 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerDeserializer.java +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerDeserializer.java @@ -1,7 +1,8 @@ package org.argeo.server; -import javax.servlet.http.HttpServletRequest; +import java.io.Reader; + public interface ServerDeserializer { - public Object deserialize(Object obj, HttpServletRequest request); + public Object deserialize(Reader str); } diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java index d075d3205..ff5ee0287 100644 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java @@ -3,17 +3,28 @@ package org.argeo.server.mvc; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.server.ServerAnswer; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; public class DefaultHandlerExceptionResolver implements HandlerExceptionResolver { + private final static Log log = LogFactory + .getLog(DefaultHandlerExceptionResolver.class); public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView mv = new ModelAndView(); - mv.addObject(ServerAnswer.error(ex)); + ServerAnswer serverAnswer = ServerAnswer.error(ex); + mv.addObject(serverAnswer); + + if (log.isDebugEnabled()) + log.error(serverAnswer); + + mv.setViewName("500"); + // response.setStatus(500); return mv; } diff --git a/server/runtime/org.argeo.server.json/.classpath b/server/runtime/org.argeo.server.json/.classpath index 16f01e2ee..6254cacb8 100644 --- a/server/runtime/org.argeo.server.json/.classpath +++ b/server/runtime/org.argeo.server.json/.classpath @@ -1,6 +1,7 @@ + diff --git a/server/runtime/org.argeo.server.json/pom.xml b/server/runtime/org.argeo.server.json/pom.xml index 182f74d4c..b12c17b1a 100644 --- a/server/runtime/org.argeo.server.json/pom.xml +++ b/server/runtime/org.argeo.server.json/pom.xml @@ -57,6 +57,14 @@ org.springframework org.springframework.web.servlet + + org.springframework.osgi + org.springframework.osgi.core + + + org.eclipse.osgi + org.eclipse.osgi + @@ -64,5 +72,18 @@ com.springsource.javax.servlet + + + org.slf4j + com.springsource.slf4j.org.apache.commons.logging + + + + + org.junit + com.springsource.junit + test + + diff --git a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/GenericJsonDeserializer.java b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/GenericJsonDeserializer.java new file mode 100644 index 000000000..c91f76d36 --- /dev/null +++ b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/GenericJsonDeserializer.java @@ -0,0 +1,73 @@ +package org.argeo.server.json; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.server.ArgeoServerException; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.ObjectCodec; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.ObjectMapper; + +public class GenericJsonDeserializer extends JsonDeserializer { + private final static Log log = LogFactory + .getLog(GenericJsonDeserializer.class); + + private JsonFactory jsonFactory = new JsonFactory(); + private ObjectCodec objectCodec = new ObjectMapper(); + + private String typeField = "type"; + + private List objectFactories = new ArrayList(); + + @Override + public T deserialize(JsonParser parser, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + // first read as Json DOM in order to extract the type + // TODO: optimize with streaming API + JsonNode root = parser.readValueAsTree(); + String type = root.get(typeField).getTextValue(); + + // Write it back as a string + StringWriter writer = new StringWriter(); + JsonGenerator generator = jsonFactory.createJsonGenerator(writer); + generator.setCodec(objectCodec); + generator.writeTree(root); + String str = writer.toString(); + + if (log.isDebugEnabled()) + log.debug("Deserialize object of type=" + type + ", str=" + str); + + JsonObjectFactory objectFactory = null; + jofs: for (JsonObjectFactory jof : objectFactories) { + if (jof.supports(type)) { + objectFactory = jof; + break jofs; + } + } + + if (objectFactory == null) + throw new ArgeoServerException( + "Cannot find JSON object factory for type " + type); + + return (T) objectFactory.readValue(type, str); + } + + public void setTypeField(String typeField) { + this.typeField = typeField; + } + + public void setObjectFactories(List objectFactories) { + this.objectFactories = objectFactories; + } + +} diff --git a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonObjectFactory.java b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonObjectFactory.java new file mode 100644 index 000000000..b3ef50f68 --- /dev/null +++ b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonObjectFactory.java @@ -0,0 +1,8 @@ +package org.argeo.server.json; + + +public interface JsonObjectFactory { + public Boolean supports(String type); + + public T readValue(String type, String str); +} diff --git a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonObjectFactoryImpl.java b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonObjectFactoryImpl.java new file mode 100644 index 000000000..cd6c00ee4 --- /dev/null +++ b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonObjectFactoryImpl.java @@ -0,0 +1,113 @@ +package org.argeo.server.json; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.server.ArgeoServerException; +import org.codehaus.jackson.map.ObjectMapper; +import org.osgi.framework.BundleContext; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.osgi.context.BundleContextAware; +import org.springframework.osgi.util.BundleDelegatingClassLoader; + +public class JsonObjectFactoryImpl implements JsonObjectFactory, + BundleContextAware, InitializingBean { + private final static Log log = LogFactory + .getLog(JsonObjectFactoryImpl.class); + + private BundleContext bundleContext; + private BundleDelegatingClassLoader classLoader; + + private ObjectMapper objectMapper = new ObjectMapper(); + private Map supportedTypes = new HashMap(); + + public Boolean supports(String type) { + if (supportedTypes.containsKey(type)) + return true; + + return loadClass(type) != null ? true : false; + // try { + // // Class.forName(type); + // Thread.currentThread().getContextClassLoader().loadClass(type); + // return true; + // } catch (ClassNotFoundException e) { + // return false; + // } + } + + public T readValue(String type, String str) { + final Class clss; + if (supportedTypes.containsKey(type)) + clss = supportedTypes.get(type); + else { + clss = loadClass(type); + if (clss == null) + throw new ArgeoServerException("Cannot find type " + type); + // try { + // // clss = Class.forName(type); + // clss = Thread.currentThread().getContextClassLoader() + // .loadClass(type); + // } catch (ClassNotFoundException e) { + // throw new ArgeoServerException("Cannot find type " + type, e); + // } + } + + try { + return (T) objectMapper.readValue(str, clss); + } catch (Exception e) { + throw new ArgeoServerException("Cannot deserialize " + str + + " (type=" + type + ")", e); + } + } + + public void setSupportedTypes(Map supportedTypes) { + this.supportedTypes = supportedTypes; + } + + protected Class loadClass(String type) { + Class clss; +// try { +// return Class.forName(type); +// } catch (ClassNotFoundException e) { +// if (log.isDebugEnabled()) +// log.debug("Class.forName failed: " + e); +// } +// +// try { +// return Thread.currentThread().getContextClassLoader().loadClass( +// type); +// } catch (ClassNotFoundException e) { +// if (log.isDebugEnabled()) +// log +// .debug("Thread.currentThread().getContextClassLoader().loadClass failed: " +// + e); +// } +// +// try { +// return getClass().getClassLoader().loadClass(type); +// } catch (ClassNotFoundException e) { +// if (log.isDebugEnabled()) +// log.debug("getClass().getClassLoader().loadClass failed: " + e); +// } +// + try { + return classLoader.loadClass(type); + } catch (ClassNotFoundException e) { + if (log.isDebugEnabled()) + log.debug("BundleDelegatingClassLoader.loadClass failed: " + e); + } + + return null; + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + public void afterPropertiesSet() throws Exception { + classLoader = BundleDelegatingClassLoader + .createBundleClassLoaderFor(bundleContext.getBundle()); + } +} diff --git a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonServerMapper.java b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonServerMapper.java index 4ab128e0b..8fef8e6b2 100644 --- a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonServerMapper.java +++ b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonServerMapper.java @@ -1,53 +1,78 @@ package org.argeo.server.json; -import java.io.BufferedReader; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.Reader; +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.server.ArgeoServerException; import org.argeo.server.ServerDeserializer; -import org.argeo.server.ServerSerializer; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.DeserializationProblemHandler; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.deser.CustomDeserializerFactory; +import org.codehaus.jackson.map.deser.StdDeserializerProvider; +import org.springframework.beans.factory.InitializingBean; -public class JsonServerMapper implements ServerSerializer, ServerDeserializer { - private JsonFactory jsonFactory = new JsonFactory(); - private ObjectMapper objectMapper = new ObjectMapper(); +public class JsonServerMapper extends JsonServerSerializer implements + ServerDeserializer, InitializingBean { + private final static Log log = LogFactory.getLog(JsonServerMapper.class); - public void serialize(Object obj, HttpServletRequest request, - HttpServletResponse response) { - try { - response.setContentType("application/json"); + private Class targetClass; - JsonGenerator jsonGenerator = jsonFactory - .createJsonGenerator(response.getWriter()); - jsonGenerator.useDefaultPrettyPrinter(); + private Map deserializers = new HashMap(); - objectMapper.writeValue(jsonGenerator, obj); - } catch (Exception e) { - throw new ArgeoServerException("Cannot serialize " + obj, e); + public void afterPropertiesSet() throws Exception { + CustomDeserializerFactory dsf = new CustomDeserializerFactory(); + for (Class clss : deserializers.keySet()) { + dsf.addSpecificMapping(clss, deserializers.get(clss)); } + StdDeserializerProvider sdp = new StdDeserializerProvider(dsf); + getObjectMapper().setDeserializerProvider(sdp); + // ignore unkown properties + getObjectMapper().getDeserializationConfig().addHandler( + new DeserializationProblemHandler() { + public boolean handleUnknownProperty( + DeserializationContext ctxt, + JsonDeserializer deserializer, Object bean, + String propertyName) throws IOException, + JsonProcessingException { + if (log.isDebugEnabled()) + log.debug("Ignore property " + propertyName); + return true; + } + }); } - public Object deserialize(Object obj, HttpServletRequest request) { + public Object deserialize(Reader reader) { try { - String body = request.getParameter("body"); - if (body == null) { - // lets read the message body instead - BufferedReader reader = request.getReader(); - StringBuffer buffer = new StringBuffer(); - String line = null; - while (((line = reader.readLine()) != null)) { - buffer.append(line); - } - body = buffer.toString(); - } - return objectMapper.readValue(body, Object.class); + // String body = request.getParameter("body"); + // if (body == null) { + // // lets read the message body instead + // BufferedReader reader = request.getReader(); + // StringBuffer buffer = new StringBuffer(); + // String line = null; + // while (((line = reader.readLine()) != null)) { + // buffer.append(line); + // } + // body = buffer.toString(); + // } + return getObjectMapper().readValue(reader, targetClass); } catch (Exception e) { - throw new ArgeoServerException("Cannot deserialize " + request, e); + throw new ArgeoServerException("Cannot deserialize " + reader, e); } + + } + + public void setTargetClass(Class targetClass) { + this.targetClass = targetClass; + } + + public void setDeserializers(Map deserializers) { + this.deserializers = deserializers; } } diff --git a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonServerSerializer.java b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonServerSerializer.java new file mode 100644 index 000000000..1c38bbe15 --- /dev/null +++ b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/JsonServerSerializer.java @@ -0,0 +1,59 @@ +package org.argeo.server.json; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.server.ArgeoServerException; +import org.argeo.server.ServerSerializer; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.ObjectMapper; + +public class JsonServerSerializer implements ServerSerializer { + private final static Log log = LogFactory + .getLog(JsonServerSerializer.class); + + private JsonFactory jsonFactory = new JsonFactory(); + private ObjectMapper objectMapper = new ObjectMapper(); + + private Boolean prettyPrint = true; + + public void serialize(Object obj, HttpServletRequest request, + HttpServletResponse response) { + JsonGenerator jsonGenerator = null; + try { + response.setContentType("application/json"); + + jsonGenerator = jsonFactory.createJsonGenerator(response + .getWriter()); + if (prettyPrint) + jsonGenerator.useDefaultPrettyPrinter(); + + objectMapper.writeValue(jsonGenerator, obj); + + jsonGenerator.close(); + } catch (Exception e) { + throw new ArgeoServerException("Cannot serialize " + obj, e); + } finally { + if (jsonGenerator != null) + try { + jsonGenerator.close(); + } catch (IOException e) { + if (log.isTraceEnabled()) + log.error("Cannot close JSON generator", e); + } + } + } + + public void setPrettyPrint(Boolean prettyPrint) { + this.prettyPrint = prettyPrint; + } + + protected ObjectMapper getObjectMapper() { + return objectMapper; + } +} diff --git a/server/runtime/org.argeo.server.json/src/test/java/org/argeo/server/json/JsonServerMapperTest.java b/server/runtime/org.argeo.server.json/src/test/java/org/argeo/server/json/JsonServerMapperTest.java new file mode 100644 index 000000000..d73c598a3 --- /dev/null +++ b/server/runtime/org.argeo.server.json/src/test/java/org/argeo/server/json/JsonServerMapperTest.java @@ -0,0 +1,8 @@ +package org.argeo.server.json; + +public class JsonServerMapperTest { + public void testDeserialize() { + JsonServerMapper mapper = new JsonServerMapper(); + //mapper.setTargetClass(targetClass) + } +}