From 62a87e0195f69747aa5168ebecfebd8626442ba8 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Tue, 15 Sep 2009 18:48:35 +0000 Subject: [PATCH] Explore JSon approach git-svn-id: https://svn.argeo.org/commons/trunk@2926 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../org.argeo.security.core/.classpath | 1 + .../runtime/org.argeo.security.core/pom.xml | 16 ++++ .../org/argeo/security/BasicArgeoUser.java | 47 +++++++++ .../java/org/argeo/security/UserNature.java | 47 ++++++++- .../argeo/security/core/ArgeoUserDetails.java | 8 +- .../argeo/security/json/ArgeoUserMapper.java | 84 ++++++++++++++++ .../ldap/CoworkerUserNatureMapper.java | 38 ++++++++ .../security/ldap/SimpleUserNatureMapper.java | 21 +--- .../argeo/security/nature/CoworkerNature.java | 34 +++++++ .../security/nature/SimpleUserNature.java | 33 +------ .../security/json/ArgeoUserJsonTest.java | 95 +++++++++++++++++++ 11 files changed, 370 insertions(+), 54 deletions(-) create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/json/ArgeoUserMapper.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/CoworkerUserNatureMapper.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/CoworkerNature.java create mode 100644 security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/json/ArgeoUserJsonTest.java diff --git a/security/runtime/org.argeo.security.core/.classpath b/security/runtime/org.argeo.security.core/.classpath index 16f01e2ee..bab5b6519 100644 --- a/security/runtime/org.argeo.security.core/.classpath +++ b/security/runtime/org.argeo.security.core/.classpath @@ -1,6 +1,7 @@ + diff --git a/security/runtime/org.argeo.security.core/pom.xml b/security/runtime/org.argeo.security.core/pom.xml index d5a031d17..51aca0eac 100644 --- a/security/runtime/org.argeo.security.core/pom.xml +++ b/security/runtime/org.argeo.security.core/pom.xml @@ -56,6 +56,13 @@ org.springframework.security + + + org.codehaus.jackson + com.springsource.org.codehaus.jackson.mapper + 1.0.0 + + com.springsource.json com.springsource.json @@ -66,5 +73,14 @@ com.springsource.org.antlr + + + + + org.junit + com.springsource.junit + test + + 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 index 000000000..df910d57e --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/BasicArgeoUser.java @@ -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 userNatures = new ArrayList(); + private List roles = new ArrayList(); + + public BasicArgeoUser() { + + } + + public BasicArgeoUser(ArgeoUser argeoUser) { + username = argeoUser.getUsername(); + userNatures = new ArrayList(argeoUser.getUserNatures()); + roles = new ArrayList(argeoUser.getRoles()); + } + + public List getUserNatures() { + return userNatures; + } + + public List getRoles() { + return roles; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public void setUserNatures(List userNatures) { + this.userNatures = userNatures; + } + + public void setRoles(List roles) { + this.roles = roles; + } +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserNature.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserNature.java index eceed3980..e2487b9ba 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserNature.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserNature.java @@ -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(); + } } diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java index 4a6882af4..1f82ee949 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java @@ -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 userInfos; + private final List userNatures; private final List roles; - public ArgeoUserDetails(String username, List userInfos, + public ArgeoUserDetails(String username, List 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 roles = new ArrayList(); @@ -30,7 +30,7 @@ public class ArgeoUserDetails extends User implements ArgeoUser { } public List getUserNatures() { - return userInfos; + return userNatures; } public List 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 index 000000000..55e22b711 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/json/ArgeoUserMapper.java @@ -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 { + 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 clss = (Class) 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 index 000000000..6fb0ef048 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/CoworkerUserNatureMapper.java @@ -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; + } + +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SimpleUserNatureMapper.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SimpleUserNatureMapper.java index aae342699..6a6bab3c7 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SimpleUserNatureMapper.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ldap/SimpleUserNatureMapper.java @@ -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 index 000000000..24f1c9b16 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/CoworkerNature.java @@ -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; + } + +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/SimpleUserNature.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/SimpleUserNature.java index 1aac27ab7..da31bbae7 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/SimpleUserNature.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/nature/SimpleUserNature.java @@ -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 index 000000000..02b2529bb --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/test/java/org/argeo/security/json/ArgeoUserJsonTest.java @@ -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 natures = new ArrayList(); + + 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 natures = new ArrayList(); + 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 + } +} -- 2.30.2