View Javadoc

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  			// The object received is not a LDAP Bean, return null
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 }