Explore JSon approach
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 15 Sep 2009 18:48:35 +0000 (18:48 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 15 Sep 2009 18:48:35 +0000 (18:48 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@2926 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

security/runtime/org.argeo.security.core/.classpath
security/runtime/org.argeo.security.core/pom.xml
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java [new file with mode: 0644]
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserNature.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/json/ArgeoUserMapper.java [new file with mode: 0644]
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/CoworkerUserNatureMapper.java [new file with mode: 0644]
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SimpleUserNatureMapper.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/CoworkerNature.java [new file with mode: 0644]
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/SimpleUserNature.java
security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/json/ArgeoUserJsonTest.java [new file with mode: 0644]

index 16f01e2ee7b671c44c26c453773dab706e98da1e..bab5b6519cb35d626d1749afcb047740c3971f90 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
        <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+       <classpathentry kind="src" path="src/test/java"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
        <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
        <classpathentry kind="output" path="target/classes"/>
index d5a031d17d5cd698d64a8dd72aaabeb1e367b037..51aca0eac1c3f166bb5503fcce1e7ba298437f61 100644 (file)
                        <artifactId>org.springframework.security</artifactId>
                </dependency>
 
+               <!-- JSON  -->
+               <dependency>
+                       <groupId>org.codehaus.jackson</groupId>
+                       <artifactId>com.springsource.org.codehaus.jackson.mapper</artifactId>
+                       <version>1.0.0</version>
+               </dependency>
+
                <dependency>
                        <groupId>com.springsource.json</groupId>
                        <artifactId>com.springsource.json</artifactId>
                        <artifactId>com.springsource.org.antlr</artifactId>
                </dependency>
 
+
+
+               <!-- TEST -->
+               <dependency>
+                       <groupId>org.junit</groupId>
+                       <artifactId>com.springsource.junit</artifactId>
+                       <scope>test</scope>
+               </dependency>
+
        </dependencies>
 </project>
diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java
new file mode 100644 (file)
index 0000000..df910d5
--- /dev/null
@@ -0,0 +1,47 @@
+package org.argeo.security;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BasicArgeoUser implements ArgeoUser, Serializable {
+       private static final long serialVersionUID = 1L;
+
+       private String username;
+       private List<UserNature> userNatures = new ArrayList<UserNature>();
+       private List<String> roles = new ArrayList<String>();
+
+       public BasicArgeoUser() {
+
+       }
+
+       public BasicArgeoUser(ArgeoUser argeoUser) {
+               username = argeoUser.getUsername();
+               userNatures = new ArrayList<UserNature>(argeoUser.getUserNatures());
+               roles = new ArrayList<String>(argeoUser.getRoles());
+       }
+
+       public List<UserNature> getUserNatures() {
+               return userNatures;
+       }
+
+       public List<String> getRoles() {
+               return roles;
+       }
+
+       public String getUsername() {
+               return username;
+       }
+
+       public void setUsername(String username) {
+               this.username = username;
+       }
+
+       public void setUserNatures(List<UserNature> userNatures) {
+               this.userNatures = userNatures;
+       }
+
+       public void setRoles(List<String> roles) {
+               this.roles = roles;
+       }
+}
index eceed398005fb04b3075341ce7565e59568a60c3..e2487b9ba7051b36b6a54d6d78a4c67dc585e85d 100644 (file)
@@ -1,5 +1,50 @@
 package org.argeo.security;
 
-public interface UserNature {
+import java.util.UUID;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.jackson.annotate.JsonAnySetter;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonMethod;
+
+//@JsonAutoDetect(value = { JsonMethod.GETTER, JsonMethod.SETTER })
+public class UserNature {
+       private final static Log log = LogFactory.getLog(UserNature.class);
+
+       private String uuid = UUID.randomUUID().toString();
+       private String type;
+
+       public String getUuid() {
+               return uuid;
+       }
+
+       public void setUuid(String uuid) {
+               this.uuid = uuid;
+       }
+
+       public String getType() {
+               if (type != null)
+                       return type;
+               else
+                       return getClass().getName();
+       }
+
+       public void setType(String type) {
+               this.type = type;
+       }
+
+       @JsonAnySetter
+       public void anySetter(String key, Object obj) {
+               if (obj != null)
+                       log.info("anySetter: " + key + "=" + obj + " (" + obj.getClass()
+                                       + "), natureType=" + type);
+       }
+
+       @JsonCreator
+       public static Object valueOf(String str) {
+               log.info("create: " + str);
+               return new UserNature();
+       }
 }
index 4a6882af432a666acb470b7c9aa3a5c9c816fadb..1f82ee949ae639ac837a95472f1227f1de90b3d7 100644 (file)
@@ -12,14 +12,14 @@ import org.springframework.security.userdetails.User;
 public class ArgeoUserDetails extends User implements ArgeoUser {
        private static final long serialVersionUID = 1L;
 
-       private final List<UserNature> userInfos;
+       private final List<UserNature> userNatures;
        private final List<String> roles;
 
-       public ArgeoUserDetails(String username, List<UserNature> userInfos,
+       public ArgeoUserDetails(String username, List<UserNature> userNatures,
                        String password, GrantedAuthority[] authorities)
                        throws IllegalArgumentException {
                super(username, password, true, true, true, true, authorities);
-               this.userInfos = Collections.unmodifiableList(userInfos);
+               this.userNatures = Collections.unmodifiableList(userNatures);
                
                // Roles
                List<String> roles = new ArrayList<String>();
@@ -30,7 +30,7 @@ public class ArgeoUserDetails extends User implements ArgeoUser {
        }
 
        public List<UserNature> getUserNatures() {
-               return userInfos;
+               return userNatures;
        }
 
        public List<String> getRoles() {
diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/json/ArgeoUserMapper.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/json/ArgeoUserMapper.java
new file mode 100644 (file)
index 0000000..55e22b7
--- /dev/null
@@ -0,0 +1,84 @@
+package org.argeo.security.json;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+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.UserNature;
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.DeserializationContext;
+import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.deser.CustomDeserializerFactory;
+import org.codehaus.jackson.map.deser.StdDeserializerProvider;
+
+public class ArgeoUserMapper {
+       private final static Log log = LogFactory.getLog(ArgeoUserMapper.class);
+
+       private String userNatureTypeField = "type";
+
+       private ObjectMapper mapper = new ObjectMapper();
+
+       public ArgeoUserMapper() {
+               CustomDeserializerFactory dsf = new CustomDeserializerFactory();
+               dsf.addSpecificMapping(UserNature.class, new UserNatureDeserializer());
+               StdDeserializerProvider sdp = new StdDeserializerProvider(dsf);
+               mapper.setDeserializerProvider(sdp);
+       }
+
+       public ArgeoUser parse(String content) throws JsonMappingException,
+                       JsonParseException, IOException {
+
+               return mapper.readValue(content, BasicArgeoUser.class);
+       }
+
+       private class UserNatureDeserializer extends JsonDeserializer<UserNature> {
+               private JsonFactory jsonFactory = new JsonFactory();
+
+               @Override
+               public UserNature deserialize(JsonParser parser,
+                               DeserializationContext dc) throws IOException,
+                               JsonProcessingException {
+                       try {
+                               // first read as Json DOM in order to extract the type
+                               // TODO: optimize with streaming API
+                               JsonNode root = parser.readValueAsTree();
+                               String type = root.get(userNatureTypeField).getTextValue();
+
+                               // Write it back as a string
+                               StringWriter writer = new StringWriter();
+                               JsonGenerator generator = jsonFactory
+                                               .createJsonGenerator(writer);
+                               generator.setCodec(mapper);
+                               generator.writeTree(root);
+                               String str = writer.toString();
+
+                               log.info("type=" + type + ", str=" + str);
+
+                               // TODO: use context classloader (in OSGi)
+                               // TODO: externalize type/classes mapping
+                               Class<UserNature> clss = (Class<UserNature>) Class
+                                               .forName(type);
+                               UserNature result = mapper.readValue(str, clss);
+
+                               // JavaType javaType = TypeFactory.fromClass(clss);
+                               // BeanDeserializer bd = new BeanDeserializer(javaType);
+                               // JsonParser parser2 = jsonFactory.createJsonParser(str);
+
+                               return result;
+                       } catch (ClassNotFoundException e) {
+                               throw new RuntimeException("Cannot deserialize", e);
+                       }
+               }
+
+       }
+}
diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/CoworkerUserNatureMapper.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/CoworkerUserNatureMapper.java
new file mode 100644 (file)
index 0000000..6fb0ef0
--- /dev/null
@@ -0,0 +1,38 @@
+package org.argeo.security.ldap;
+
+import org.argeo.security.UserNature;
+import org.argeo.security.nature.CoworkerNature;
+import org.springframework.ldap.core.DirContextAdapter;
+import org.springframework.ldap.core.DirContextOperations;
+
+public class CoworkerUserNatureMapper implements UserNatureMapper {
+
+       public UserNature mapUserInfoFromContext(DirContextOperations ctx) {
+               CoworkerNature basicUserInfo = new CoworkerNature();
+               basicUserInfo.setDescription(ctx.getStringAttribute("description"));
+               basicUserInfo.setMobile(ctx.getStringAttribute("mobile"));
+               basicUserInfo.setTelephoneNumber(ctx
+                               .getStringAttribute("telephoneNumber"));
+               return basicUserInfo;
+       }
+
+       public void mapUserInfoToContext(UserNature userInfoArg, DirContextAdapter ctx) {
+               CoworkerNature userInfo = (CoworkerNature) userInfoArg;
+               if (userInfo.getDescription() != null) {
+                       ctx.setAttributeValue("description", userInfo.getDescription());
+               }
+               if (userInfo.getMobile() == null || !userInfo.getMobile().equals("")) {
+                       ctx.setAttributeValue("mobile", userInfo.getMobile());
+               }
+               if (userInfo.getTelephoneNumber() == null
+                               || !userInfo.getTelephoneNumber().equals("")) {
+                       ctx.setAttributeValue("telephoneNumber", userInfo
+                                       .getTelephoneNumber());
+               }
+       }
+
+       public Boolean supports(UserNature userInfo) {
+               return userInfo instanceof CoworkerNature;
+       }
+
+}
index aae34269979378aca8d122159587e427d29effa6..6a6bab3c786b5cbf783271f645aa7fe0de81f59d 100644 (file)
@@ -12,30 +12,17 @@ public class SimpleUserNatureMapper implements UserNatureMapper {
                basicUserInfo.setLastName(ctx.getStringAttribute("sn"));
                basicUserInfo.setFirstName(ctx.getStringAttribute("givenName"));
                basicUserInfo.setEmail(ctx.getStringAttribute("mail"));
-               basicUserInfo.setDescription(ctx.getStringAttribute("description"));
-               basicUserInfo.setMobile(ctx.getStringAttribute("mobile"));
-               basicUserInfo.setTelephoneNumber(ctx
-                               .getStringAttribute("telephoneNumber"));
                return basicUserInfo;
        }
 
-       public void mapUserInfoToContext(UserNature userInfoArg, DirContextAdapter ctx) {
+       public void mapUserInfoToContext(UserNature userInfoArg,
+                       DirContextAdapter ctx) {
                SimpleUserNature userInfo = (SimpleUserNature) userInfoArg;
-               ctx.setAttributeValue("cn", userInfo.getFullName());
+               ctx.setAttributeValue("cn", userInfo.getFirstName() + " "
+                               + userInfo.getLastName());
                ctx.setAttributeValue("sn", userInfo.getLastName());
                ctx.setAttributeValue("givenName", userInfo.getFirstName());
                ctx.setAttributeValue("mail", userInfo.getEmail());
-               if (userInfo.getDescription() != null) {
-                       ctx.setAttributeValue("description", userInfo.getDescription());
-               }
-               if (userInfo.getMobile() == null || !userInfo.getMobile().equals("")) {
-                       ctx.setAttributeValue("mobile", userInfo.getMobile());
-               }
-               if (userInfo.getTelephoneNumber() == null
-                               || !userInfo.getTelephoneNumber().equals("")) {
-                       ctx.setAttributeValue("telephoneNumber", userInfo
-                                       .getTelephoneNumber());
-               }
        }
 
        public Boolean supports(UserNature userInfo) {
diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/CoworkerNature.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/CoworkerNature.java
new file mode 100644 (file)
index 0000000..24f1c9b
--- /dev/null
@@ -0,0 +1,34 @@
+package org.argeo.security.nature;
+
+import org.argeo.security.UserNature;
+
+public class CoworkerNature extends UserNature {
+       private String description;
+       private String mobile;
+       private String telephoneNumber;
+
+       public String getDescription() {
+               return description;
+       }
+
+       public void setDescription(String description) {
+               this.description = description;
+       }
+
+       public String getMobile() {
+               return mobile;
+       }
+
+       public void setMobile(String mobile) {
+               this.mobile = mobile;
+       }
+
+       public String getTelephoneNumber() {
+               return telephoneNumber;
+       }
+
+       public void setTelephoneNumber(String telephoneNumber) {
+               this.telephoneNumber = telephoneNumber;
+       }
+
+}
index 1aac27ab742c7c52afb05596f4f39e2296dcf49c..da31bbae77b7eabf40b91f113158590e4eee1c75 100644 (file)
@@ -2,13 +2,10 @@ package org.argeo.security.nature;
 
 import org.argeo.security.UserNature;
 
-public class SimpleUserNature implements UserNature {
+public class SimpleUserNature extends UserNature {
        private String email;
        private String firstName;
        private String lastName;
-       private String description;
-       private String mobile;
-       private String telephoneNumber;
 
        public String getEmail() {
                return email;
@@ -34,32 +31,4 @@ public class SimpleUserNature implements UserNature {
                this.lastName = lastName;
        }
 
-       public String getDescription() {
-               return description;
-       }
-
-       public void setDescription(String description) {
-               this.description = description;
-       }
-
-       public String getFullName() {
-               return getFirstName() + " " + getLastName();
-       }
-
-       public String getMobile() {
-               return mobile;
-       }
-
-       public void setMobile(String mobile) {
-               this.mobile = mobile;
-       }
-
-       public String getTelephoneNumber() {
-               return telephoneNumber;
-       }
-
-       public void setTelephoneNumber(String telephoneNumber) {
-               this.telephoneNumber = telephoneNumber;
-       }
-
 }
diff --git a/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/json/ArgeoUserJsonTest.java b/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/json/ArgeoUserJsonTest.java
new file mode 100644 (file)
index 0000000..02b2529
--- /dev/null
@@ -0,0 +1,95 @@
+package org.argeo.security.json;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+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.UserNature;
+import org.argeo.security.core.ArgeoUserDetails;
+import org.argeo.security.nature.CoworkerNature;
+import org.argeo.security.nature.SimpleUserNature;
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.springframework.security.GrantedAuthority;
+import org.springframework.security.GrantedAuthorityImpl;
+
+import com.springsource.json.writer.JSONArray;
+import com.springsource.json.writer.JSONObject;
+
+public class ArgeoUserJsonTest extends TestCase {
+       private static Log log = LogFactory.getLog(ArgeoUserJsonTest.class);
+
+       public void testMapper() throws Exception {
+               List<UserNature> natures = new ArrayList<UserNature>();
+
+               SimpleUserNature sun = new SimpleUserNature();
+               sun.setFirstName("Mickey");
+               sun.setEmail("username@domain.com");
+               natures.add(sun);
+
+               CoworkerNature cwn = new CoworkerNature();
+               cwn.setMobile("+123456789");
+               natures.add(cwn);
+
+               GrantedAuthority[] roles = { new GrantedAuthorityImpl("ROLE1"),
+                               new GrantedAuthorityImpl("ROLE2") };
+               ArgeoUserDetails argeoUserDetails = new ArgeoUserDetails("USER",
+                               natures, "PASSWORD", roles);
+
+               BasicArgeoUser argeoUser = new BasicArgeoUser(argeoUserDetails);
+
+               StringWriter writer = new StringWriter();
+
+               JsonFactory jsonFactory = new JsonFactory();
+               JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(writer);
+               jsonGenerator.useDefaultPrettyPrinter();
+
+               ObjectMapper objectMapper = new ObjectMapper();
+
+               objectMapper.writeValue(jsonGenerator, argeoUser);
+               String audJo = writer.toString();
+
+               log.info("audJo:\n" + audJo);
+
+               // BasicArgeoUser aud = objectMapper.readValue(audJo,
+               // BasicArgeoUser.class);
+
+               ArgeoUserMapper argeoUserMapper = new ArgeoUserMapper();
+               ArgeoUser argeoUserDes = argeoUserMapper.parse(audJo);
+       }
+
+       public void testSeriDeserialize() {
+               List<UserNature> natures = new ArrayList<UserNature>();
+               JSONArray naturesJo = new JSONArray();
+
+               SimpleUserNature sun = new SimpleUserNature();
+               sun.setEmail("username@domain.com");
+               natures.add(sun);
+               naturesJo.put(new JSONObject(sun));
+
+               CoworkerNature cwn = new CoworkerNature();
+               cwn.setMobile("+123456789");
+               natures.add(cwn);
+               naturesJo.put(new JSONObject(cwn));
+
+               GrantedAuthority[] roles = { new GrantedAuthorityImpl("ROLE1"),
+                               new GrantedAuthorityImpl("ROLE1") };
+               ArgeoUserDetails argeoUserDetails = new ArgeoUserDetails("USER",
+                               natures, "PASSWORD", roles);
+
+               JSONObject argeoUserDetailsJo = new JSONObject(argeoUserDetails);
+               argeoUserDetailsJo.put("userNatures", naturesJo);
+
+               log.info("argeoUserDetailsJo=" + argeoUserDetailsJo.toString(2));
+
+               // JSONParser jsonParser = new JSONParser();
+               // ArgeoUserDetails argeoUserDetails = JSONParser
+       }
+}