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;
import org.jivesoftware.openfire.group.GroupProvider;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveConstants;
import org.xmpp.packet.JID;
......@@ -40,8 +39,6 @@ import java.util.regex.Pattern;
public class LdapGroupProvider implements GroupProvider {
private LdapManager manager;
private String baseDN;
private String alternateBaseDN;
private UserManager userManager;
private String[] standardAttributes;
private int groupCount = -1;
......@@ -52,8 +49,6 @@ public class LdapGroupProvider implements GroupProvider {
*/
public LdapGroupProvider() {
manager = LdapManager.getInstance();
baseDN = manager.getBaseDN();
alternateBaseDN = manager.getAlternateBaseDN();
userManager = UserManager.getInstance();
standardAttributes = new String[3];
standardAttributes[0] = manager.getGroupNameField();
......@@ -140,115 +135,16 @@ public class LdapGroupProvider implements GroupProvider {
if (groupCount != -1 && System.currentTimeMillis() < expiresStamp) {
return groupCount;
}
int count = 0;
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1);
LdapContext ctx = null;
LdapContext ctx2 = null;
try {
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);
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;
List<String> groups = manager.retrieveList(
manager.getGroupNameField(),
MessageFormat.format(manager.getGroupSearchFilter(), "*"),
-1,
-1,
null
);
this.groupCount = groups.size();
this.expiresStamp = System.currentTimeMillis() + JiveConstants.MINUTE *5;
return count;
return this.groupCount;
}
public Collection<String> getGroupNames() {
......@@ -256,155 +152,13 @@ public class LdapGroupProvider implements GroupProvider {
}
public Collection<String> getGroupNames(int startIndex, int numResults) {
List<String> groupNames = 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 = 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;
return manager.retrieveList(
manager.getGroupNameField(),
MessageFormat.format(manager.getGroupSearchFilter(), "*"),
startIndex,
numResults,
null
);
}
public Collection<String> getGroupNames(JID user) {
......@@ -432,39 +186,6 @@ public class LdapGroupProvider implements GroupProvider {
if (username == null || "".equals(username)) {
return Collections.emptyList();
}
// Perform the LDAP query
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1);
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false);
List<String> groupNames = new ArrayList<String>();
LdapContext ctx = null;
LdapContext ctx2 = null;
try {
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(), "*"));
......@@ -473,95 +194,14 @@ public class LdapGroupProvider implements GroupProvider {
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 {
try {
if (ctx != null) {
ctx.setRequestControls(null);
ctx.close();
}
if (ctx2 != null) {
ctx2.setRequestControls(null);
ctx2.close();
}
}
catch (Exception ignored) {
// Ignore.
}
}
return groupNames;
// Perform the LDAP query
return manager.retrieveList(
manager.getGroupNameField(),
filter.toString(),
-1,
-1,
null
);
}
/**
......@@ -624,280 +264,22 @@ public class LdapGroupProvider implements GroupProvider {
if (!query.endsWith("*")) {
query = query + "*";
}
List<String> groupNames = 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 = 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("(").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;
// Perform the LDAP query
return manager.retrieveList(
manager.getGroupNameField(),
filter.toString(),
startIndex,
numResults,
null
);
}
public boolean isSearchSupported() {
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 {
XMPPServer server = XMPPServer.getInstance();
String serverName = server.getServerInfo().getXMPPDomain();
......@@ -969,6 +351,7 @@ public class LdapGroupProvider implements GroupProvider {
}
}
catch (Exception e) {
// TODO: A NPE is occuring here
Log.error(e);
}
}
......
......@@ -23,8 +23,7 @@ import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
......@@ -1466,4 +1465,185 @@ public class LdapManager {
this.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;
import org.jivesoftware.util.Log;
import org.xmpp.packet.JID;
import javax.naming.NamingEnumeration;
import javax.naming.directory.*;
import javax.naming.ldap.*;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;
......@@ -37,16 +35,12 @@ public class LdapUserProvider implements UserProvider {
private static SimpleDateFormat ldapDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
private LdapManager manager;
private String baseDN;
private String alternateBaseDN;
private Map<String, String> searchFields;
private int userCount = -1;
private long expiresStamp = System.currentTimeMillis();
public LdapUserProvider() {
manager = LdapManager.getInstance();
baseDN = manager.getBaseDN();
alternateBaseDN = manager.getAlternateBaseDN();
searchFields = new LinkedHashMap<String,String>();
String fieldList = JiveGlobals.getXMLProperty("ldap.searchFields");
// If the value isn't present, default to to username, name, and email.
......@@ -141,250 +135,26 @@ public class LdapUserProvider implements UserProvider {
if (userCount != -1 && System.currentTimeMillis() < expiresStamp) {
return userCount;
}
int count = 0;
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1);
LdapContext ctx = null;
LdapContext ctx2 = null;
try {
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);
// 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;
List<String> users = manager.retrieveList(
manager.getUsernameField(),
MessageFormat.format(manager.getSearchFilter(), "*"),
-1,
-1,
null
);
this.userCount = users.size();
this.expiresStamp = System.currentTimeMillis() + JiveConstants.MINUTE *5;
return count;
return this.userCount;
}
public Collection<String> getUsernames() {
Set<String> usernames = new HashSet<String>();
LdapContext ctx = null;
LdapContext ctx2 = null;
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1);
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false);
try {
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;
return manager.retrieveList(
manager.getUsernameField(),
MessageFormat.format(manager.getSearchFilter(), "*"),
-1,
-1,
null
);
}
public Collection<User> getUsers() {
......@@ -392,176 +162,14 @@ public class LdapUserProvider implements UserProvider {
}
public Collection<User> getUsers(int startIndex, int numResults) {
List<String> usernames = 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 = 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() });
// 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()]));
List<String> userlist = manager.retrieveList(
manager.getUsernameField(),
MessageFormat.format(manager.getSearchFilter(), "*"),
startIndex,
numResults,
manager.getUsernameSuffix()
);
return new UserCollection(userlist.toArray(new String[userlist.size()]));
}
public void setName(String username, String name) throws UserNotFoundException {
......@@ -626,43 +234,11 @@ public class LdapUserProvider implements UserProvider {
if (!query.endsWith("*")) {
query = query + "*";
}
int pageSize = JiveGlobals.getXMLProperty("ldap.pagedResultsSize", -1);
Boolean clientSideSort = JiveGlobals.getXMLProperty("ldap.clientSideSorting", false);
List<String> usernames = new ArrayList<String>();
LdapContext ctx = null;
LdapContext ctx2 = null;
try {
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 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(MessageFormat.format(manager.getSearchFilter(),"*"));
filter.append(")");
if (fields.size() > 1) {
filter.append("(|");
......@@ -675,130 +251,14 @@ public class LdapUserProvider implements UserProvider {
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) {
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()]));
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() {
......
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