1 package net.sf.jldapbeans.lang;
2
3 import java.beans.BeanInfo;
4 import java.beans.Introspector;
5 import java.beans.PropertyDescriptor;
6 import java.lang.reflect.Method;
7 import java.util.Enumeration;
8 import java.util.Hashtable;
9 import java.util.Iterator;
10 import java.util.List;
11
12 import javax.naming.Context;
13 import javax.naming.Name;
14 import javax.naming.NamingException;
15 import javax.naming.directory.Attribute;
16 import javax.naming.directory.Attributes;
17 import javax.naming.directory.BasicAttribute;
18 import javax.naming.directory.BasicAttributes;
19 import javax.naming.ldap.LdapContext;
20 import javax.naming.ldap.LdapName;
21 import javax.naming.spi.DirStateFactory;
22
23 import net.sf.jldapbeans.lang.annotation.LdapAttribute;
24 import net.sf.jldapbeans.lang.annotation.LdapBean;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 /***
30 * The <code>LdapStateFactory</code> is the entry point of the mechanism that stores
31 * a <code>LdapBean</code> object as a LDAP object.
32 *
33 * @author <a href="mailto:alonsoft@users.sf.net">A. Alonso Domínguez</a>
34 * @version 1.0 $ Revision 29-oct-2005 :: 11:58:46 :: alonso $
35 *
36 */
37 public class LdapStateFactory implements DirStateFactory {
38 private static final Log log = LogFactory.getLog(LdapStateFactory.class);
39
40 public Object getStateToBind(Object obj, Name name, Context ctx, Hashtable env)
41 throws NamingException { return null; }
42
43 public Result getStateToBind(Object obj, Name name, Context ctx, Hashtable env,
44 Attributes attrs)
45 throws NamingException {
46 if(!(ctx instanceof LdapContext)) return null;
47 if(name.toString().equals("cn=Subschema")) return null;
48
49 LdapClass beanClass = null;
50 try {
51 beanClass = LdapClass.classOf(obj);
52 }
53 catch(LdapClassException e) {
54
55 return null;
56 }
57
58 log.debug("Storing LDAP Bean [" + beanClass + "] with name [" + name + "]");
59
60 try {
61 BasicAttributes resultAttrs = readAttributes(obj, beanClass);
62 resultAttrs.put(getObjectClass(beanClass));
63 ((LdapObject) obj).contextualize(new LdapName(name.toString()), (LdapContext) ctx);
64 return new Result(null, resultAttrs);
65 }
66 catch(Exception e) {
67 NamingException ex = new NamingException(e.getMessage());
68 ex.setRootCause(e);
69 throw ex;
70 }
71 }
72
73 protected Attribute getObjectClass(LdapClass ldapClass) {
74 BasicAttribute result = new BasicAttribute("objectClass");
75
76 for(Class<?> clazz : ldapClass.getClasses()) {
77 LdapBean ldapBean = clazz.getAnnotation(LdapBean.class);
78 result.add(ldapBean.name()[0]);
79 }
80
81 return result;
82 }
83
84 protected Attributes mergeAttributes(Attributes attr1, Attributes attr2, boolean overwrite) {
85 BasicAttributes result = new BasicAttributes();
86 Enumeration e = attr1.getAll();
87 while(e.hasMoreElements()) {
88 Attribute attr = (Attribute) e.nextElement();
89 result.put(attr);
90 }
91 e = attr2.getAll();
92 while(e.hasMoreElements()) {
93 Attribute attr = (Attribute) e.nextElement();
94 if(result.get(attr.getID()) == null)
95 result.put(attr);
96 else if(overwrite) result.put(attr);
97 }
98 return result;
99 }
100
101 private BasicAttributes readAttributes(Object bean, LdapClass ldapClass) throws Exception {
102 BasicAttributes result = new BasicAttributes();
103 for(Class<?> clazz : ldapClass.getClasses()) {
104 BeanInfo bi = Introspector.getBeanInfo(clazz);
105 for(PropertyDescriptor property : bi.getPropertyDescriptors()) {
106 Method read = property.getReadMethod();
107 if(!read.isAnnotationPresent(LdapAttribute.class)) continue;
108
109 LdapAttribute ldapAttr = read.getAnnotation(LdapAttribute.class);
110 String attrID = ldapAttr.name()[0];
111 if(attrID.equals("[undefined]")) attrID = property.getName();
112
113 log.debug("Reading attribute [" + attrID + "]");
114 BasicAttribute attr = new BasicAttribute(attrID);
115 Object value = read.invoke(bean, new Object[]{});
116 if(value == null) continue;
117
118 if(value instanceof List) {
119 Iterator it = ((List) value).iterator();
120 while(it.hasNext())
121 attr.add(it.next());
122 }
123 else attr.add(value);
124
125 if(attr.size() > 0) result.put(attr);
126 }
127 }
128 return result;
129 }
130
131 }