Commit 353e262e authored by Daniel Henninger's avatar Daniel Henninger Committed by dhenninger

[JM-1117] Paged result fixes.

Centralized LDAP list query handling.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@10035 b35dd754-fafc-0310-a699-88a17e54d16e
parent 7ac12cab
...@@ -17,7 +17,6 @@ import org.jivesoftware.openfire.group.GroupNotFoundException; ...@@ -17,7 +17,6 @@ import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.group.GroupProvider; import org.jivesoftware.openfire.group.GroupProvider;
import org.jivesoftware.openfire.user.UserManager; import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException; import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveConstants; import org.jivesoftware.util.JiveConstants;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
...@@ -40,8 +39,6 @@ import java.util.regex.Pattern; ...@@ -40,8 +39,6 @@ import java.util.regex.Pattern;
public class LdapGroupProvider implements GroupProvider { public class LdapGroupProvider implements GroupProvider {
private LdapManager manager; private LdapManager manager;
private String baseDN;
private String alternateBaseDN;
private UserManager userManager; private UserManager userManager;
private String[] standardAttributes; private String[] standardAttributes;
private int groupCount = -1; private int groupCount = -1;
...@@ -52,8 +49,6 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -52,8 +49,6 @@ public class LdapGroupProvider implements GroupProvider {
*/ */
public LdapGroupProvider() { public LdapGroupProvider() {
manager = LdapManager.getInstance(); manager = LdapManager.getInstance();
baseDN = manager.getBaseDN();
alternateBaseDN = manager.getAlternateBaseDN();
userManager = UserManager.getInstance(); userManager = UserManager.getInstance();
standardAttributes = new String[3]; standardAttributes = new String[3];
standardAttributes[0] = manager.getGroupNameField(); standardAttributes[0] = manager.getGroupNameField();
...@@ -140,115 +135,16 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -140,115 +135,16 @@ public class LdapGroupProvider implements GroupProvider {
if (groupCount != -1 && System.currentTimeMillis() < expiresStamp) { if (groupCount != -1 && System.currentTimeMillis() < expiresStamp) {
return groupCount; return groupCount;
} }
List<String> groups = manager.retrieveList(
int count = 0; manager.getGroupNameField(),
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1); MessageFormat.format(manager.getGroupSearchFilter(), "*"),
LdapContext ctx = null; -1,
LdapContext ctx2 = null; -1,
try { null
ctx = manager.getContext(baseDN); );
this.groupCount = groups.size();
// Set up request controls, if appropriate.
List<Control> tmpRequestControls = new ArrayList<Control>();
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getGroupNameField() });
String filter = MessageFormat.format(manager.getGroupSearchFilter(), "*");
NamingEnumeration answer = ctx.search("", filter, searchControls);
byte[] cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine results on this page
while (answer.hasMoreElements()) {
answer.next();
count++;
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
// Add count of groups found in alternate DN
if (alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
answer = ctx2.search("", filter, searchControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine results on this page
while (answer.hasMoreElements()) {
count++;
answer.nextElement();
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
// Close the enumeration.
answer.close();
}
catch (Exception e) {
Log.error(e);
}
finally {
try {
if (ctx != null) {
ctx.setRequestControls(null);
ctx.close();
}
if (ctx2 != null) {
ctx2.setRequestControls(null);
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
this.groupCount = count;
this.expiresStamp = System.currentTimeMillis() + JiveConstants.MINUTE *5; this.expiresStamp = System.currentTimeMillis() + JiveConstants.MINUTE *5;
return count; return this.groupCount;
} }
public Collection<String> getGroupNames() { public Collection<String> getGroupNames() {
...@@ -256,155 +152,13 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -256,155 +152,13 @@ public class LdapGroupProvider implements GroupProvider {
} }
public Collection<String> getGroupNames(int startIndex, int numResults) { public Collection<String> getGroupNames(int startIndex, int numResults) {
List<String> groupNames = new ArrayList<String>(); return manager.retrieveList(
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1); manager.getGroupNameField(),
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false); MessageFormat.format(manager.getGroupSearchFilter(), "*"),
LdapContext ctx = null; startIndex,
LdapContext ctx2 = null; numResults,
try { null
ctx = manager.getContext(baseDN); );
// Set up request controls, if appropriate.
List<Control> tmpRequestControls = new ArrayList<Control>();
if (!clientSideSort) {
// Server side sort on username field.
tmpRequestControls.add(new SortControl(new String[]{manager.getUsernameField()}, Control.NONCRITICAL));
}
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getGroupNameField() });
String filter = MessageFormat.format(manager.getGroupSearchFilter(), "*");
NamingEnumeration answer = ctx.search("", filter, searchControls);
// If server side sort, we'll skip the initial ones we don't want, and stop when we've hit
// the amount we do want.
int skip = -1;
int lastRes = -1;
if (!clientSideSort) {
skip = startIndex;
lastRes = startIndex + numResults;
}
byte[] cookie = null;
int count = 0;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all of the results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next group.
String groupName = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getGroupNameField()).get();
// Escape group name and add to results.
groupNames.add(JID.escapeNode(groupName));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
// Add groups found in alternate DN
if (count <= lastRes && alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
ctx2.setRequestControls(requestControls);
answer = ctx2.search("", filter, searchControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all of the results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next group.
String groupName = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getGroupNameField()).get();
// Escape group name and add to results.
groupNames.add(JID.escapeNode(groupName));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
// Close the enumeration.
answer.close();
// If client-side sorting is enabled, sort.
if (clientSideSort) {
Collections.sort(groupNames);
}
}
catch (Exception e) {
Log.error(e);
}
finally {
try {
if (ctx != null) {
ctx.setRequestControls(null);
ctx.close();
}
if (ctx2 != null) {
ctx2.setRequestControls(null);
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
return groupNames;
} }
public Collection<String> getGroupNames(JID user) { public Collection<String> getGroupNames(JID user) {
...@@ -432,136 +186,22 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -432,136 +186,22 @@ public class LdapGroupProvider implements GroupProvider {
if (username == null || "".equals(username)) { if (username == null || "".equals(username)) {
return Collections.emptyList(); return Collections.emptyList();
} }
// Perform the LDAP query StringBuilder filter = new StringBuilder();
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1); filter.append("(&");
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false); filter.append(MessageFormat.format(manager.getGroupSearchFilter(), "*"));
List<String> groupNames = new ArrayList<String>(); filter.append("(").append(manager.getGroupMemberField()).append("=").append(username);
LdapContext ctx = null; filter.append("))");
LdapContext ctx2 = null; if (Log.isDebugEnabled()) {
try { Log.debug("Trying to find group names for user: " + user + " using query: " + filter.toString());
ctx = manager.getContext(baseDN);
// Set up request controls, if appropriate.
List<Control> tmpRequestControls = new ArrayList<Control>();
if (!clientSideSort) {
// Server side sort on username field.
tmpRequestControls.add(new SortControl(new String[]{manager.getUsernameField()}, Control.NONCRITICAL));
}
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
// Search for the dn based on the group name.
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getGroupNameField() });
StringBuilder filter = new StringBuilder();
filter.append("(&");
filter.append(MessageFormat.format(manager.getGroupSearchFilter(), "*"));
filter.append("(").append(manager.getGroupMemberField()).append("=").append(username);
filter.append("))");
if (Log.isDebugEnabled()) {
Log.debug("Trying to find group names for user: " + user + " using query: " + filter.toString());
}
NamingEnumeration answer = ctx.search("", filter.toString(), searchControls);
byte[] cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
// Get the next group.
String groupName = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getGroupNameField()).get();
// Escape group name and add to results.
groupNames.add(JID.escapeNode(groupName));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
if (alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
ctx2.setRequestControls(requestControls);
answer = ctx2.search("", filter.toString(), searchControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
// Get the next group.
String groupName = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getGroupNameField()).get();
// Escape group name and add to results.
groupNames.add(JID.escapeNode(groupName));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
// Close the enumeration.
answer.close();
// If client-side sorting is enabled, sort.
if (clientSideSort) {
Collections.sort(groupNames);
}
}
catch (Exception e) {
Log.error("Error getting groups for user: " + user, e);
return Collections.emptyList();
} }
finally { // Perform the LDAP query
try { return manager.retrieveList(
if (ctx != null) { manager.getGroupNameField(),
ctx.setRequestControls(null); filter.toString(),
ctx.close(); -1,
} -1,
if (ctx2 != null) { null
ctx2.setRequestControls(null); );
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
return groupNames;
} }
/** /**
...@@ -624,280 +264,22 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -624,280 +264,22 @@ public class LdapGroupProvider implements GroupProvider {
if (!query.endsWith("*")) { if (!query.endsWith("*")) {
query = query + "*"; query = query + "*";
} }
List<String> groupNames = new ArrayList<String>(); StringBuilder filter = new StringBuilder();
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1); filter.append("(").append(manager.getGroupNameField()).append("=").append(query).append(")");
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false); // Perform the LDAP query
LdapContext ctx = null; return manager.retrieveList(
LdapContext ctx2 = null; manager.getGroupNameField(),
try { filter.toString(),
ctx = manager.getContext(baseDN); startIndex,
numResults,
// Set up request controls, if appropriate. null
List<Control> tmpRequestControls = new ArrayList<Control>(); );
if (!clientSideSort) {
// Server side sort on username field.
tmpRequestControls.add(new SortControl(new String[]{manager.getUsernameField()}, Control.NONCRITICAL));
}
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
// Search for the dn based on the group name.
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getGroupNameField() });
StringBuilder filter = new StringBuilder();
filter.append("(").append(manager.getGroupNameField()).append("=").append(query).append(")");
NamingEnumeration answer = ctx.search("", filter.toString(), searchControls);
// If server side sort, we'll skip the initial ones we don't want, and stop when we've hit
// the amount we do want.
int skip = -1;
int lastRes = -1;
if (!clientSideSort) {
skip = startIndex;
lastRes = startIndex + numResults;
}
byte[] cookie = null;
int count = 0;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next group.
String groupName = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getGroupNameField()).get();
// Escape group name and add to results.
groupNames.add(JID.escapeNode(groupName));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
if (count <= lastRes && alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
ctx2.setRequestControls(requestControls);
answer = ctx2.search("", filter.toString(), searchControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next group.
String groupName = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getGroupNameField()).get();
// Escape group name and add to results.
groupNames.add(JID.escapeNode(groupName));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
// Close the enumeration.
answer.close();
// If client-side sorting is enabled, sort.
if (clientSideSort) {
Collections.sort(groupNames);
}
}
catch (Exception e) {
Log.error(e);
}
finally {
try {
if (ctx != null) {
ctx.setRequestControls(null);
ctx.close();
}
if (ctx2 != null) {
ctx2.setRequestControls(null);
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
return groupNames;
} }
public boolean isSearchSupported() { public boolean isSearchSupported() {
return true; return true;
} }
/**
* An auxilary method used to populate LDAP groups based on a provided LDAP search result.
*
* @param answer LDAP search result.
* @return a collection of groups.
* @throws javax.naming.NamingException if there was an exception with the LDAP query.
*/
private Collection<Group> populateGroups(Enumeration<SearchResult> answer) throws NamingException {
if (manager.isDebugEnabled()) {
Log.debug("LdapGroupProvider: Starting to populate groups with users.");
}
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1);
LdapContext ctx = null;
LdapContext ctx2 = null;
try {
TreeMap<String, Group> groups = new TreeMap<String, Group>();
ctx = manager.getContext(baseDN);
// Set up request controls, if appropriate.
List<Control> tmpRequestControls = new ArrayList<Control>();
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
byte[] cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
String name = "";
try {
Group group = processGroup(ctx, answer.nextElement().getAttributes());
name = group.getName();
groups.put(name, group);
}
catch (Exception e) {
Log.error("LdapGroupProvider: Error while populating group, " + name + ".", e);
}
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
if (alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
ctx2.setRequestControls(requestControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
String name = "";
try {
Group group = processGroup(ctx, answer.nextElement().getAttributes());
name = group.getName();
groups.put(name, group);
}
catch (Exception e) {
Log.error("LdapGroupProvider: Error while populating group, " + name + ".", e);
}
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
if (manager.isDebugEnabled()) {
Log.debug("LdapGroupProvider: Finished populating group(s) with users.");
}
return groups.values();
}
catch (Exception e) {
Log.error("Exception while attempting to populate groups and members: ", e);
return new ArrayList<Group>();
}
finally {
try {
if (ctx != null) {
ctx.close();
}
if (ctx2 != null) {
ctx2.close();
}
}
catch (Exception e) {
// Ignore.
}
}
}
private Group processGroup(LdapContext ctx, Attributes a) throws NamingException { private Group processGroup(LdapContext ctx, Attributes a) throws NamingException {
XMPPServer server = XMPPServer.getInstance(); XMPPServer server = XMPPServer.getInstance();
String serverName = server.getServerInfo().getXMPPDomain(); String serverName = server.getServerInfo().getXMPPDomain();
...@@ -969,6 +351,7 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -969,6 +351,7 @@ public class LdapGroupProvider implements GroupProvider {
} }
} }
catch (Exception e) { catch (Exception e) {
// TODO: A NPE is occuring here
Log.error(e); Log.error(e);
} }
} }
......
...@@ -23,8 +23,7 @@ import javax.naming.directory.DirContext; ...@@ -23,8 +23,7 @@ import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext; import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls; import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult; import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.*;
import javax.naming.ldap.LdapContext;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
...@@ -1466,4 +1465,185 @@ public class LdapManager { ...@@ -1466,4 +1465,185 @@ public class LdapManager {
this.groupSearchFilter = groupSearchFilter; this.groupSearchFilter = groupSearchFilter;
properties.put("ldap.groupSearchFilter", groupSearchFilter); properties.put("ldap.groupSearchFilter", groupSearchFilter);
} }
/**
* Generic routine for retrieving a list of results from the LDAP server. It's meant to be very
* flexible so that just about any query for a list of results can make use of it without having
* to reimplement their own calls to LDAP. This routine also accounts for sorting settings,
* paging settings, any other global settings, and alternate DNs.
*
* The passed in filter string needs to be pre-prepared! In other words, nothing will be changed
* in the string before it is used as a string.
*
* @param attribute LDAP attribute to be pulled from each result and placed in the return results.
* Typically pulled from this manager.
* @param searchFilter Filter to use to perform the search. Typically pulled from this manager.
* @param startIndex Number/index of first result to include in results. (-1 for no limit)
* @param numResults Number of results to include. (-1 for no limit)
* @param suffixToTrim An arbitrary string to trim from the end of every attribute returned. null to disable.
* @return A simple list of strings (that should be sorted) of the results.
*/
public List<String> retrieveList(String attribute, String searchFilter, int startIndex, int numResults, String suffixToTrim) {
List<String> results = new ArrayList<String>();
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1);
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false);
LdapContext ctx = null;
LdapContext ctx2 = null;
try {
ctx = getContext(baseDN);
// Set up request controls, if appropriate.
List<Control> tmpRequestControls = new ArrayList<Control>();
if (!clientSideSort) {
// Server side sort on username field.
tmpRequestControls.add(new SortControl(new String[]{attribute}, Control.NONCRITICAL));
}
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { attribute });
// If server side sort, we'll skip the initial ones we don't want, and stop when we've hit
// the amount we do want.
int skip = -1;
int lastRes = -1;
if (!clientSideSort) {
skip = startIndex;
lastRes = startIndex + numResults;
}
byte[] cookie = null;
int count = 0;
// Run through all pages of results (one page is also possible ;) )
do {
NamingEnumeration answer = ctx.search("", searchFilter, searchControls);
// Examine all of the results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next result.
String result = (String)((SearchResult)answer.next()).getAttributes().get(
attribute).get();
// Remove suffixToTrim if set
if (suffixToTrim != null && suffixToTrim.length() > 0 && result.endsWith(suffixToTrim)) {
result = result.substring(0,result.length()-suffixToTrim.length());
}
// Add this to the result.
results.add(result);
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
// Close the enumeration.
answer.close();
} while (cookie != null);
// Add groups found in alternate DN
if (count <= lastRes && alternateBaseDN != null) {
ctx2 = getContext(alternateBaseDN);
ctx2.setRequestControls(requestControls);
NamingEnumeration answer = ctx2.search("", searchFilter, searchControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all of the results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next result.
String result = (String)((SearchResult)answer.next()).getAttributes().get(
attribute).get();
// Remove suffixToTrim if set
if (suffixToTrim != null && suffixToTrim.length() > 0 && result.endsWith(suffixToTrim)) {
result = result.substring(0,result.length()-suffixToTrim.length());
}
// Add this to the result.
results.add(result);
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
// Close the enumeration.
answer.close();
} while (cookie != null);
}
// If client-side sorting is enabled, sort.
if (clientSideSort) {
Collections.sort(results);
}
}
catch (Exception e) {
Log.error(e);
}
finally {
try {
if (ctx != null) {
ctx.setRequestControls(null);
ctx.close();
}
if (ctx2 != null) {
ctx2.setRequestControls(null);
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
return results;
}
// TODO: Create a count version of this so we don't pull all of the information into a huge array for no reason
} }
\ No newline at end of file
...@@ -18,9 +18,7 @@ import org.jivesoftware.util.JiveGlobals; ...@@ -18,9 +18,7 @@ import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import javax.naming.NamingEnumeration;
import javax.naming.directory.*; import javax.naming.directory.*;
import javax.naming.ldap.*;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
...@@ -37,16 +35,12 @@ public class LdapUserProvider implements UserProvider { ...@@ -37,16 +35,12 @@ public class LdapUserProvider implements UserProvider {
private static SimpleDateFormat ldapDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); private static SimpleDateFormat ldapDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
private LdapManager manager; private LdapManager manager;
private String baseDN;
private String alternateBaseDN;
private Map<String, String> searchFields; private Map<String, String> searchFields;
private int userCount = -1; private int userCount = -1;
private long expiresStamp = System.currentTimeMillis(); private long expiresStamp = System.currentTimeMillis();
public LdapUserProvider() { public LdapUserProvider() {
manager = LdapManager.getInstance(); manager = LdapManager.getInstance();
baseDN = manager.getBaseDN();
alternateBaseDN = manager.getAlternateBaseDN();
searchFields = new LinkedHashMap<String,String>(); searchFields = new LinkedHashMap<String,String>();
String fieldList = JiveGlobals.getXMLProperty("ldap.searchFields"); String fieldList = JiveGlobals.getXMLProperty("ldap.searchFields");
// If the value isn't present, default to to username, name, and email. // If the value isn't present, default to to username, name, and email.
...@@ -141,250 +135,26 @@ public class LdapUserProvider implements UserProvider { ...@@ -141,250 +135,26 @@ public class LdapUserProvider implements UserProvider {
if (userCount != -1 && System.currentTimeMillis() < expiresStamp) { if (userCount != -1 && System.currentTimeMillis() < expiresStamp) {
return userCount; return userCount;
} }
int count = 0; List<String> users = manager.retrieveList(
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1); manager.getUsernameField(),
LdapContext ctx = null; MessageFormat.format(manager.getSearchFilter(), "*"),
LdapContext ctx2 = null; -1,
try { -1,
ctx = manager.getContext(baseDN); null
);
// Set up request controls, if appropriate. this.userCount = users.size();
List<Control> tmpRequestControls = new ArrayList<Control>();
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
// Search for the dn based on the username.
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
String filter = MessageFormat.format(manager.getSearchFilter(), "*");
NamingEnumeration answer = ctx.search("", filter, searchControls);
byte[] cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine results on this page
while (answer.hasMoreElements()) {
count++;
answer.nextElement();
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
// Add count of users found in alternate DN
if (alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
answer = ctx2.search("", filter, searchControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine results on this page
while (answer.hasMoreElements()) {
count++;
answer.nextElement();
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
// Close the enumeration.
answer.close();
}
catch (Exception e) {
Log.error(e);
}
finally {
try {
if (ctx != null) {
ctx.close();
}
}
catch (Exception ignored) {
// Ignore.
}
try {
if (ctx2 != null) {
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
this.userCount = count;
this.expiresStamp = System.currentTimeMillis() + JiveConstants.MINUTE *5; this.expiresStamp = System.currentTimeMillis() + JiveConstants.MINUTE *5;
return count; return this.userCount;
} }
public Collection<String> getUsernames() { public Collection<String> getUsernames() {
Set<String> usernames = new HashSet<String>(); return manager.retrieveList(
LdapContext ctx = null; manager.getUsernameField(),
LdapContext ctx2 = null; MessageFormat.format(manager.getSearchFilter(), "*"),
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1); -1,
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false); -1,
try { null
ctx = manager.getContext(baseDN); );
// Set up request controls, if appropriate.
List<Control> tmpRequestControls = new ArrayList<Control>();
if (!clientSideSort) {
// Server side sort on username field.
tmpRequestControls.add(new SortControl(new String[]{manager.getUsernameField()}, Control.NONCRITICAL));
}
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
// Search for the dn based on the username.
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
String filter = MessageFormat.format(manager.getSearchFilter(), "*");
NamingEnumeration answer = ctx.search("", filter, searchControls);
byte[] cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all of the results on this page
while (answer.hasMoreElements()) {
// Get the next userID.
String username = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getUsernameField()).get();
// Escape username and add to results.
usernames.add(JID.escapeNode(username));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
// Add usernames found in alternate DN
if (alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
ctx2.setRequestControls(requestControls);
answer = ctx2.search("", filter, searchControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all of the results on this page
while (answer.hasMoreElements()) {
// Get the next userID.
String username = (String) ((SearchResult) answer.next()).getAttributes().get(
manager.getUsernameField()).get();
// Escape username and add to results.
usernames.add(JID.escapeNode(username));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
// Close the enumeration.
answer.close();
}
catch (Exception e) {
Log.error(e);
}
finally {
try {
if (ctx != null) {
ctx.setRequestControls(null);
ctx.close();
}
}
catch (Exception ignored) {
// Ignore.
}
try {
if (ctx2 != null) {
ctx2.setRequestControls(null);
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
// If client-side sorting is enabled, do it.
if (clientSideSort) {
Collections.sort(new ArrayList<String>(usernames));
}
return usernames;
} }
public Collection<User> getUsers() { public Collection<User> getUsers() {
...@@ -392,176 +162,14 @@ public class LdapUserProvider implements UserProvider { ...@@ -392,176 +162,14 @@ public class LdapUserProvider implements UserProvider {
} }
public Collection<User> getUsers(int startIndex, int numResults) { public Collection<User> getUsers(int startIndex, int numResults) {
List<String> usernames = new ArrayList<String>(); List<String> userlist = manager.retrieveList(
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1); manager.getUsernameField(),
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false); MessageFormat.format(manager.getSearchFilter(), "*"),
LdapContext ctx = null; startIndex,
LdapContext ctx2 = null; numResults,
try { manager.getUsernameSuffix()
ctx = manager.getContext(baseDN); );
return new UserCollection(userlist.toArray(new String[userlist.size()]));
// Set up request controls, if appropriate.
List<Control> tmpRequestControls = new ArrayList<Control>();
if (!clientSideSort) {
// Server side sort on username field.
tmpRequestControls.add(new SortControl(new String[]{manager.getUsernameField()}, Control.NONCRITICAL));
}
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
// Search for the dn based on the username.
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
// Limit results to those we'll need to process unless client-side sorting
// is turned on.
if (!clientSideSort) {
searchControls.setCountLimit(startIndex+numResults);
}
String filter = MessageFormat.format(manager.getSearchFilter(), "*");
NamingEnumeration answer = ctx.search("", filter, searchControls);
// If client-side sorting is enabled, read in all results, sort, then get a sublist.
NamingEnumeration answer2 = null;
if (alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
ctx2.setRequestControls(requestControls);
answer2 = ctx2.search("", filter, searchControls);
}
// If server side sort, we'll skip the initial ones we don't want, and stop when we've hit
// the amount we do want.
int skip = -1;
int lastRes = -1;
if (!clientSideSort) {
skip = startIndex;
lastRes = startIndex + numResults;
}
byte[] cookie = null;
int count = 0;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next userID.
String username = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getUsernameField()).get();
// Remove usernameSuffix if set
String suffix = manager.getUsernameSuffix();
if(suffix.length() > 0 && username.endsWith(suffix)) {
username = username.substring(0,username.length()-suffix.length());
}
// Escape username and add to results.
usernames.add(JID.escapeNode(username));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
if (count <= lastRes && alternateBaseDN != null) {
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer2.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next userID.
String username = (String) ((SearchResult) answer2.next()).getAttributes().get(
manager.getUsernameField()).get();
// Remove usernameSuffix if set
String suffix = manager.getUsernameSuffix();
if(suffix.length() > 0 && username.endsWith(suffix)) {
username = username.substring(0,username.length()-suffix.length());
}
// Escape username and add to results.
usernames.add(JID.escapeNode(username));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
if (clientSideSort) {
// If we're doing client side sorting, we pulled everything in and now we sort and trim.
Collections.sort(new ArrayList<String>(usernames));
int endIndex = Math.min(startIndex + numResults, usernames.size()-1);
usernames = usernames.subList(startIndex, endIndex);
}
// Close the enumeration.
answer.close();
}
catch (Exception e) {
Log.error(e);
}
finally {
try {
if (ctx != null) {
ctx.setRequestControls(null);
ctx.close();
}
}
catch (Exception ignored) {
// Ignore.
}
try {
if (ctx2 != null) {
ctx2.setRequestControls(null);
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
return new UserCollection(usernames.toArray(new String[usernames.size()]));
} }
public void setName(String username, String name) throws UserNotFoundException { public void setName(String username, String name) throws UserNotFoundException {
...@@ -626,179 +234,31 @@ public class LdapUserProvider implements UserProvider { ...@@ -626,179 +234,31 @@ public class LdapUserProvider implements UserProvider {
if (!query.endsWith("*")) { if (!query.endsWith("*")) {
query = query + "*"; query = query + "*";
} }
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1); StringBuilder filter = new StringBuilder();
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false); //Add the global search filter so only those users the directory administrator wants to include
List<String> usernames = new ArrayList<String>(); //are returned from the directory
LdapContext ctx = null; filter.append("(&(");
LdapContext ctx2 = null; filter.append(MessageFormat.format(manager.getSearchFilter(),"*"));
try { filter.append(")");
ctx = manager.getContext(baseDN); if (fields.size() > 1) {
filter.append("(|");
// Set up request controls, if appropriate.
List<Control> tmpRequestControls = new ArrayList<Control>();
if (!clientSideSort) {
// Server side sort on username field.
tmpRequestControls.add(new SortControl(new String[]{manager.getUsernameField()}, Control.NONCRITICAL));
}
if (pageSize > -1) {
// Server side paging.
tmpRequestControls.add(new PagedResultsControl(pageSize, Control.NONCRITICAL));
}
Control[] requestControls = tmpRequestControls.toArray(new Control[tmpRequestControls.size()]);
ctx.setRequestControls(requestControls);
// Search for the dn based on the username.
SearchControls searchControls = new SearchControls();
// See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
String searchFilter = MessageFormat.format(manager.getSearchFilter(),"*");
StringBuilder filter = new StringBuilder();
//Add the global search filter so only those users the directory administrator wants to include
//are returned from the directory
filter.append("(&(");
filter.append(searchFilter);
filter.append(")");
if (fields.size() > 1) {
filter.append("(|");
}
for (String field:fields) {
String attribute = searchFields.get(field);
filter.append("(").append(attribute).append("=").append(query).append(")");
}
if (fields.size() > 1) {
filter.append(")");
}
filter.append(")");
NamingEnumeration answer = ctx.search("", filter.toString(), searchControls);
// If server side sort, we'll skip the initial ones we don't want, and stop when we've hit
// the amount we do want.
int skip = -1;
int lastRes = -1;
if (!clientSideSort) {
skip = startIndex;
lastRes = startIndex + numResults;
}
byte[] cookie = null;
int count = 0;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next userID.
String username = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getUsernameField()).get();
// Escape username and add to results.
usernames.add(JID.escapeNode(username));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
if (count <= lastRes && alternateBaseDN != null) {
ctx2 = manager.getContext(alternateBaseDN);
ctx2.setRequestControls(requestControls);
answer = ctx2.search("", filter.toString(), searchControls);
cookie = null;
// Run through all pages of results (one page is also possible ;) )
do {
// Examine all results on this page
while (answer.hasMoreElements()) {
count++;
if (skip > -1 && count < skip) {
continue;
}
if (lastRes > -1 && count > lastRes) {
break;
}
// Get the next userID.
String username = (String)((SearchResult)answer.next()).getAttributes().get(
manager.getUsernameField()).get();
// Remove usernameSuffix if set
String suffix = manager.getUsernameSuffix();
if(suffix.length() > 0 && username.endsWith(suffix)) {
username = username.substring(0,username.length()-suffix.length());
}
// Escape username and add to results.
usernames.add(JID.escapeNode(username));
}
// Examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc =
(PagedResultsResponseControl) control;
cookie = prrc.getCookie();
// Re-activate paged results
ctx.setRequestControls(new Control[]{
new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
break;
}
}
}
} while (cookie != null);
}
// Close the enumeration.
answer.close();
// If client-side sorting is enabled, sort.
if (clientSideSort) {
Collections.sort(usernames);
}
} }
catch (Exception e) { for (String field:fields) {
Log.error(e); String attribute = searchFields.get(field);
filter.append("(").append(attribute).append("=").append(query).append(")");
} }
finally { if (fields.size() > 1) {
try { filter.append(")");
if (ctx != null) {
ctx.setRequestControls(null);
ctx.close();
}
}
catch (Exception ignored) {
// Ignore.
}
try {
if (ctx2 != null) {
ctx2.setRequestControls(null);
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
} }
return new UserCollection(usernames.toArray(new String[usernames.size()])); filter.append(")");
List<String> userlist = manager.retrieveList(
manager.getUsernameField(),
filter.toString(),
startIndex,
numResults,
manager.getUsernameSuffix()
);
return new UserCollection(userlist.toArray(new String[userlist.size()]));
} }
public boolean isReadOnly() { public boolean isReadOnly() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment