support multiple OUs in LDAP component LDAPConfig class has been enhanced to support a new parameter "subDNs" which is a collection of prefixes to add to "baseDN" parameter. LDAPUserComponent has been modified to take into account the new parameters and search in a loop. Setting multiple OUs enables the usage of users from different LDAP Organization Units. Change-Id: I22fc321b4938590d717784c7eb200f3aa8c1d206 Signed-off-by: Calin CRECEA <calin.crecea@sap.com>
diff --git a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPConfig.java b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPConfig.java index 1706019..9b55640 100644 --- a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPConfig.java +++ b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPConfig.java
@@ -18,6 +18,7 @@ private String providerId; private String destination; private String baseDN; + private LDAPSubDNs subDNs; private String searchScope; private String cacheSize; @@ -61,6 +62,14 @@ this.baseDN = baseDN; } + public LDAPSubDNs getLDAPSubDNs() { + return subDNs; + } + + public void setLDAPSubDNs(LDAPSubDNs subDNs) { + this.subDNs = subDNs; + } + public String getCacheSize() { return cacheSize; }
diff --git a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPSubDNs.java b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPSubDNs.java new file mode 100644 index 0000000..6976af7 --- /dev/null +++ b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPSubDNs.java
@@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2010-2017 SAP AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * SAP AG - initial API and implementation + *******************************************************************************/ +package org.eclipse.skalli.core.user.ldap; + +import java.util.List; + +import com.thoughtworks.xstream.annotations.XStreamImplicit; + +public class LDAPSubDNs { + + @XStreamImplicit(itemFieldName="subDN") + private List<String> listSubDNs; + + // do not remove: required by xstream + public LDAPSubDNs() { + } + + public List<String> getList() { + return listSubDNs; + } + + public void setList(List<String> items) { + this.listSubDNs = items; + } + + public int size(){ + return this.listSubDNs.size(); + } + +}
diff --git a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPUserComponent.java b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPUserComponent.java index 2784a24..6c91056 100644 --- a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPUserComponent.java +++ b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPUserComponent.java
@@ -72,6 +72,7 @@ private LdapContextProvider ctxProvider; private String destination; private String baseDN; + private LDAPSubDNs subDNs; private String searchScope; private EventService eventService; @@ -134,6 +135,7 @@ ctxProvider = ctxProviders.get(providerId); destination = ldapConfig.getDestination(); baseDN = ldapConfig.getBaseDN(); + subDNs = ldapConfig.getLDAPSubDNs(); searchScope = ldapConfig.getSearchScope(); cacheSize = NumberUtils.toInt(ldapConfig.getCacheSize(), DEFAULT_CACHE_SIZE); } @@ -249,7 +251,7 @@ try { ctx = ctxProvider.getLdapContext(destination); return searchUserById(ctx, userId); - } catch (Exception e) { + } catch (Exception e) { LOG.debug(MessageFormat.format("Failed to retrieve user ''{0}''", userId), e); return new User(userId); } finally { @@ -296,24 +298,19 @@ private User searchUserById(LdapContext ctx, String userId) throws NamingException { SearchControls sc = getSearchControls(); - NamingEnumeration<SearchResult> results = null; - try { - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(sAMAccountName={0}))", userId), sc); //$NON-NLS-1$ - while (results != null && results.hasMore()) { - SearchResult entry = results.next(); - User user = processEntry(entry); - if (user != null) { - if (LOG.isDebugEnabled()) { - LOG.debug(MessageFormat.format("Success reading from LDAP: {0}, {1} <{2}>", //$NON-NLS-1$ - user.getUserId(), user.getDisplayName(), user.getEmail())); - } - return user; + ArrayList<SearchResult> results = null; + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(sAMAccountName={0}))", userId), sc, ctx);//$NON-NLS-1$ + for (SearchResult entry : results) { + User user = processEntry(entry); + if (user != null) { + if (LOG.isDebugEnabled()) { + LOG.debug(MessageFormat.format("Success reading from LDAP: {0}, {1} <{2}>", //$NON-NLS-1$ + user.getUserId(), user.getDisplayName(), user.getEmail())); } + return user; } - } finally { - closeQuietly(results); } + return new User(userId); } @@ -323,46 +320,33 @@ boolean somethingAdded = false; SearchControls sc = getSearchControls(); String[] parts = StringUtils.split(NormalizeUtil.normalize(name), " ,"); //$NON-NLS-1$ + if (parts.length == 1) { somethingAdded = search(parts[0], ret, ctx, sc); - } - else if (parts.length > 1) { + } else if (parts.length > 1) { + // givenname surname ('Michael Ochmann'), or surname givenname('Ochmann, Michael') - NamingEnumeration<SearchResult> results = null; - try { - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(givenName={0}*)(sn={1}*))", //$NON-NLS-1$ - parts[0], parts[1]), sc); - somethingAdded |= addLDAPSearchResult(ret, results); - } finally { - closeQuietly(results); - } - try { - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(sn={0}*)(givenName={1}*))", //$NON-NLS-1$ - parts[0], parts[1]), sc); - somethingAdded |= addLDAPSearchResult(ret, results); - } finally { - closeQuietly(results); - } + ArrayList<SearchResult> results = null; + + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(givenName={0}*)(sn={1}*))", //$NON-NLS-1$ + parts[0], parts[1]), sc, ctx); + somethingAdded |= addLDAPSearchResult(ret, results); + + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(sn={0}*)(givenName={1}*))", //$NON-NLS-1$ + parts[0], parts[1]), sc, ctx); + somethingAdded |= addLDAPSearchResult(ret, results); + // givenname initial surname, e.g. 'Michael R. Ochmann' if (parts.length > 2) { - try { - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(givenName={0}*)(sn={1}*))", //$NON-NLS-1$ - parts[0], parts[2]), sc); - somethingAdded |= addLDAPSearchResult(ret, results); - } finally { - closeQuietly(results); - } - try { - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(sn={0}*)(givenName={1}*))", //$NON-NLS-1$ - parts[0], parts[2]), sc); - somethingAdded |= addLDAPSearchResult(ret, results); - } finally { - closeQuietly(results); - } + + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(givenName={0}*)(sn={1}*))", //$NON-NLS-1$ + parts[0], parts[2]), sc, ctx); + somethingAdded |= addLDAPSearchResult(ret, results); + + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(sn={0}*)(givenName={1}*))", //$NON-NLS-1$ + parts[0], parts[2]), sc, ctx); + somethingAdded |= addLDAPSearchResult(ret, results); + } if (!somethingAdded) { // try to match each part individually @@ -381,53 +365,65 @@ private boolean search(String s, List<User> ret, LdapContext ctx, SearchControls sc) throws NamingException { // try a match with surname* boolean somethingAdded = false; - NamingEnumeration<SearchResult> results = null; - try { - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(|(sn={0}*)(givenName={1}*)))", s, s), sc); //$NON-NLS-1$ - somethingAdded = addLDAPSearchResult(ret, results); - } finally { - closeQuietly(results); + ArrayList<SearchResult> results = null; + + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(|(sn={0}*)(givenName={1}*)))", s, s), sc, //$NON-NLS-1$ + ctx); + somethingAdded = addLDAPSearchResult(ret, results); + + if (!somethingAdded) { + // try a match with the account name and mail address + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(sAMAccountName={0}*))", s), sc, ctx); //$NON-NLS-1$ + somethingAdded |= addLDAPSearchResult(ret, results); } if (!somethingAdded) { - try { - // try a match with the account name and mail address - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(sAMAccountName={0}*))", s), sc); //$NON-NLS-1$ - somethingAdded |= addLDAPSearchResult(ret, results); - } finally { - closeQuietly(results); - } - if (!somethingAdded) { - try { - // try to match surname~= or givenname~= - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(|(sn~={0})(givenName~={1})))", s, s), sc); //$NON-NLS-1$ - somethingAdded |= addLDAPSearchResult(ret, results); - } finally { - closeQuietly(results); - } - if (!somethingAdded) { - try { - results = ctx.search(baseDN, - MessageFormat.format("(&(objectClass=user)(mail={0}*))", s), sc); //$NON-NLS-1$ - somethingAdded |= addLDAPSearchResult(ret, results); - } finally { - closeQuietly(results); - } - } - } + // try to match surname~= or givenname~= + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(|(sn~={0})(givenName~={1})))", s, s), //$NON-NLS-1$ + sc, ctx); + somethingAdded |= addLDAPSearchResult(ret, results); } + if (!somethingAdded) { + results = ctxSearch(MessageFormat.format("(&(objectClass=user)(mail={0}*))", s), sc, ctx); //$NON-NLS-1$ + somethingAdded |= addLDAPSearchResult(ret, results); + } + return somethingAdded; } + private ArrayList<SearchResult> ctxSearch(String query, SearchControls sc, LdapContext ctx) + throws NamingException { + ArrayList<SearchResult> result = new ArrayList<SearchResult>(); + if (subDNs != null && subDNs.size() > 0){ + for (String subDN : subDNs.getList()) { + addSearchResult(result, subDN + "," + baseDN, query, sc, ctx); + } + } + else { + //in case subDNs are not set, we search only using baseDN + addSearchResult(result, baseDN, query, sc, ctx); + } + return result; + } + + private void addSearchResult(List<SearchResult> result, String dn, String query, SearchControls sc, LdapContext ctx) + throws NamingException { + NamingEnumeration<SearchResult> resultQuery = ctx.search(dn, query, sc); //$NON-NLS-1$ + try { + if (resultQuery != null && resultQuery.hasMore()) { + result.addAll(Collections.list(resultQuery)); + } + } + finally { + closeQuietly(resultQuery); + resultQuery = null; + } + } + // Iterate over a batch of search results sent by the server - private boolean addLDAPSearchResult(List<User> users, NamingEnumeration<SearchResult> results) + private boolean addLDAPSearchResult(List<User> users, ArrayList<SearchResult> results) throws NamingException { boolean somethingAdded = false; - while (results != null && results.hasMore()) { - // Display an entry - SearchResult entry = results.next(); + for (SearchResult entry : results) { User user = processEntry(entry); if (user != null) { if (LOG.isDebugEnabled()) { @@ -496,7 +492,7 @@ private void closeQuietly(LdapContext ctx) { if (ctx != null) { try { - ctx .close(); + ctx.close(); } catch (NamingException e) { LOG.error("Failed to close LDAP connection", e); }