]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapConnection.java
Change the approach for releases
[lgpl/argeo-commons.git] / org.argeo.enterprise / src / org / argeo / osgi / useradmin / LdapConnection.java
1 package org.argeo.osgi.useradmin;
2
3 import java.util.Dictionary;
4 import java.util.Hashtable;
5
6 import javax.naming.CommunicationException;
7 import javax.naming.Context;
8 import javax.naming.NameNotFoundException;
9 import javax.naming.NamingEnumeration;
10 import javax.naming.NamingException;
11 import javax.naming.directory.Attributes;
12 import javax.naming.directory.DirContext;
13 import javax.naming.directory.SearchControls;
14 import javax.naming.directory.SearchResult;
15 import javax.naming.ldap.InitialLdapContext;
16 import javax.naming.ldap.LdapName;
17
18 import org.argeo.naming.LdapAttrs;
19
20 /** A synchronized wrapper for a single {@link InitialLdapContext}. */
21 // TODO implement multiple contexts and connection pooling.
22 class LdapConnection {
23 private InitialLdapContext initialLdapContext = null;
24
25 LdapConnection(String url, Dictionary<String, ?> properties) {
26 try {
27 Hashtable<String, Object> connEnv = new Hashtable<String, Object>();
28 connEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
29 connEnv.put(Context.PROVIDER_URL, url);
30 connEnv.put("java.naming.ldap.attributes.binary", LdapAttrs.userPassword.name());
31 // use pooling in order to avoid connection timeout
32 // connEnv.put("com.sun.jndi.ldap.connect.pool", "true");
33 // connEnv.put("com.sun.jndi.ldap.connect.pool.timeout", 300000);
34
35 initialLdapContext = new InitialLdapContext(connEnv, null);
36 // StartTlsResponse tls = (StartTlsResponse) ctx
37 // .extendedOperation(new StartTlsRequest());
38 // tls.negotiate();
39 Object securityAuthentication = properties.get(Context.SECURITY_AUTHENTICATION);
40 if (securityAuthentication != null)
41 initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, securityAuthentication);
42 else
43 initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
44 Object principal = properties.get(Context.SECURITY_PRINCIPAL);
45 if (principal != null) {
46 initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, principal.toString());
47 Object creds = properties.get(Context.SECURITY_CREDENTIALS);
48 if (creds != null) {
49 initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, creds.toString());
50 }
51 }
52 } catch (Exception e) {
53 throw new UserDirectoryException("Cannot connect to LDAP", e);
54 }
55
56 }
57
58 public void init() {
59
60 }
61
62 public void destroy() {
63 try {
64 // tls.close();
65 initialLdapContext.close();
66 initialLdapContext = null;
67 } catch (NamingException e) {
68 e.printStackTrace();
69 }
70 }
71
72 protected InitialLdapContext getLdapContext() {
73 return initialLdapContext;
74 }
75
76 protected void reconnect() throws NamingException {
77 initialLdapContext.reconnect(initialLdapContext.getConnectControls());
78 }
79
80 public synchronized NamingEnumeration<SearchResult> search(LdapName searchBase, String searchFilter,
81 SearchControls searchControls) throws NamingException {
82 NamingEnumeration<SearchResult> results;
83 try {
84 results = getLdapContext().search(searchBase, searchFilter, searchControls);
85 } catch (CommunicationException e) {
86 reconnect();
87 results = getLdapContext().search(searchBase, searchFilter, searchControls);
88 }
89 return results;
90 }
91
92 public synchronized Attributes getAttributes(LdapName name) throws NamingException {
93 try {
94 return getLdapContext().getAttributes(name);
95 } catch (CommunicationException e) {
96 reconnect();
97 return getLdapContext().getAttributes(name);
98 }
99 }
100
101 synchronized void prepareChanges(UserDirectoryWorkingCopy wc) throws NamingException {
102 // make sure connection will work
103 reconnect();
104
105 // delete
106 for (LdapName dn : wc.getDeletedUsers().keySet()) {
107 if (!entryExists(dn))
108 throw new UserDirectoryException("User to delete no found " + dn);
109 }
110 // add
111 for (LdapName dn : wc.getNewUsers().keySet()) {
112 if (entryExists(dn))
113 throw new UserDirectoryException("User to create found " + dn);
114 }
115 // modify
116 for (LdapName dn : wc.getModifiedUsers().keySet()) {
117 if (!wc.getNewUsers().containsKey(dn) && !entryExists(dn))
118 throw new UserDirectoryException("User to modify not found " + dn);
119 }
120
121 }
122
123 protected boolean entryExists(LdapName dn) throws NamingException {
124 try {
125 return getAttributes(dn).size() != 0;
126 } catch (NameNotFoundException e) {
127 return false;
128 }
129 }
130
131 synchronized void commitChanges(UserDirectoryWorkingCopy wc) throws NamingException {
132 // delete
133 for (LdapName dn : wc.getDeletedUsers().keySet()) {
134 getLdapContext().destroySubcontext(dn);
135 }
136 // add
137 for (LdapName dn : wc.getNewUsers().keySet()) {
138 DirectoryUser user = wc.getNewUsers().get(dn);
139 getLdapContext().createSubcontext(dn, user.getAttributes());
140 }
141 // modify
142 for (LdapName dn : wc.getModifiedUsers().keySet()) {
143 Attributes modifiedAttrs = wc.getModifiedUsers().get(dn);
144 getLdapContext().modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, modifiedAttrs);
145 }
146 }
147 }