1 package org
.argeo
.osgi
.useradmin
;
3 import java
.util
.Dictionary
;
4 import java
.util
.Hashtable
;
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
;
18 import org
.argeo
.naming
.LdapAttrs
;
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;
25 LdapConnection(String url
, Dictionary
<String
, ?
> properties
) {
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);
35 initialLdapContext
= new InitialLdapContext(connEnv
, null);
36 // StartTlsResponse tls = (StartTlsResponse) ctx
37 // .extendedOperation(new StartTlsRequest());
39 Object securityAuthentication
= properties
.get(Context
.SECURITY_AUTHENTICATION
);
40 if (securityAuthentication
!= null)
41 initialLdapContext
.addToEnvironment(Context
.SECURITY_AUTHENTICATION
, securityAuthentication
);
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
);
49 initialLdapContext
.addToEnvironment(Context
.SECURITY_CREDENTIALS
, creds
.toString());
52 } catch (Exception e
) {
53 throw new UserDirectoryException("Cannot connect to LDAP", e
);
62 public void destroy() {
65 initialLdapContext
.close();
66 initialLdapContext
= null;
67 } catch (NamingException e
) {
72 protected InitialLdapContext
getLdapContext() {
73 return initialLdapContext
;
76 protected void reconnect() throws NamingException
{
77 initialLdapContext
.reconnect(initialLdapContext
.getConnectControls());
80 public synchronized NamingEnumeration
<SearchResult
> search(LdapName searchBase
, String searchFilter
,
81 SearchControls searchControls
) throws NamingException
{
82 NamingEnumeration
<SearchResult
> results
;
84 results
= getLdapContext().search(searchBase
, searchFilter
, searchControls
);
85 } catch (CommunicationException e
) {
87 results
= getLdapContext().search(searchBase
, searchFilter
, searchControls
);
92 public synchronized Attributes
getAttributes(LdapName name
) throws NamingException
{
94 return getLdapContext().getAttributes(name
);
95 } catch (CommunicationException e
) {
97 return getLdapContext().getAttributes(name
);
101 synchronized void prepareChanges(UserDirectoryWorkingCopy wc
) throws NamingException
{
102 // make sure connection will work
106 for (LdapName dn
: wc
.getDeletedUsers().keySet()) {
107 if (!entryExists(dn
))
108 throw new UserDirectoryException("User to delete no found " + dn
);
111 for (LdapName dn
: wc
.getNewUsers().keySet()) {
113 throw new UserDirectoryException("User to create found " + dn
);
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
);
123 protected boolean entryExists(LdapName dn
) throws NamingException
{
125 return getAttributes(dn
).size() != 0;
126 } catch (NameNotFoundException e
) {
131 synchronized void commitChanges(UserDirectoryWorkingCopy wc
) throws NamingException
{
133 for (LdapName dn
: wc
.getDeletedUsers().keySet()) {
134 getLdapContext().destroySubcontext(dn
);
137 for (LdapName dn
: wc
.getNewUsers().keySet()) {
138 DirectoryUser user
= wc
.getNewUsers().get(dn
);
139 getLdapContext().createSubcontext(dn
, user
.getAttributes());
142 for (LdapName dn
: wc
.getModifiedUsers().keySet()) {
143 Attributes modifiedAttrs
= wc
.getModifiedUsers().get(dn
);
144 getLdapContext().modifyAttributes(dn
, DirContext
.REPLACE_ATTRIBUTE
, modifiedAttrs
);