/*
* LinShare is an open source filesharing software, part of the LinPKI software
* suite, developed by Linagora.
*
* Copyright (C) 2015 LINAGORA
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version, provided you comply with the Additional Terms applicable for
* LinShare software by Linagora pursuant to Section 7 of the GNU Affero General
* Public License, subsections (b), (c), and (e), pursuant to which you must
* notably (i) retain the display of the “LinShare™” trademark/logo at the top
* of the interface window, the display of the “You are using the Open Source
* and free version of LinShare™, powered by Linagora © 2009–2015. Contribute to
* Linshare R&D by subscribing to an Enterprise offer!” infobox and in the
* e-mails sent with the Program, (ii) retain all hypertext links between
* LinShare and linshare.org, between linagora.com and Linagora, and (iii)
* refrain from infringing Linagora intellectual property rights over its
* trademarks and commercial brands. Other Additional Terms apply, see
* <http://www.linagora.com/licenses/> for more details.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License and
* its applicable Additional Terms for LinShare along with this program. If not,
* see <http://www.gnu.org/licenses/> for the GNU Affero General Public License
* version 3 and <http://www.linagora.com/licenses/> for the Additional Terms
* applicable to LinShare software.
*/
package org.linagora.linshare.ldap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.naming.CommunicationException;
import javax.naming.LimitExceededException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.HasControls;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.PagedResultsControl;
import javax.naming.ldap.PagedResultsResponseControl;
import org.linid.dm.authorization.lql.dnlist.DnList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LinShareDnList extends DnList {
final static protected Logger logger = LoggerFactory
.getLogger(LinShareDnList.class);
protected int pageSize;
protected int sizeLimit;
public LinShareDnList() {
super();
this.pageSize = 50;
this.sizeLimit = 50;
}
public LinShareDnList(int searchPageSize, int searchSizeLimit) {
super();
this.pageSize = searchPageSize;
this.sizeLimit = searchSizeLimit;
}
@Override
public List<String> getDnList(LdapContext ldapCtx, String base,
String filter, int scope) throws NamingException {
if (pageSize == 0) {
return getDnListNoPagination(ldapCtx, base, filter, scope);
} else {
return getDnListWithPagination(ldapCtx, base, filter, scope);
}
}
private List<String> getDnListWithPagination(LdapContext ldapCtx,
String base, String filter, int scope) throws NamingException {
List<String> cList = new ArrayList<String>();
SearchControls scs = new SearchControls();
scs.setSearchScope(scope);
scs.setDerefLinkFlag(true);
if (sizeLimit != 0) {
if(pageSize == sizeLimit) {
scs.setCountLimit(sizeLimit + 1);
} else {
scs.setCountLimit(sizeLimit);
}
}
try {
// Setting pagination control.
ldapCtx.setRequestControls(new Control[] { new PagedResultsControl(
pageSize, Control.CRITICAL) });
// No attributes will be return. Official LDAP syntax
scs.setReturningAttributes(new String[] { "1.1" });
byte[] cookie = null;
int nbResult = 0;
do {
NamingEnumeration<SearchResult> results = ldapCtx.search(base,
filter, scs);
while (results != null && results.hasMore()) {
SearchResult entry = (SearchResult) results.next();
if (logger.isDebugEnabled()) {
logger.debug("entry name : " + entry.getName());
}
// Handle the entry's response controls (if any)
if (entry instanceof HasControls) {
Control[] controls = ((HasControls) entry)
.getControls();
if (logger.isDebugEnabled()) {
logger.debug("entry name has controls "
+ controls.toString());
}
}
String dn = entry.getName();
if (base.length() > 0) {
dn += "," + base;
}
cList.add(dn);
nbResult += 1;
}
// Examine the paged results control response
Control[] controls = ldapCtx.getResponseControls();
if (controls != null) {
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
// int estimatedTotal = prrc.getResultSize();
cookie = prrc.getCookie();
} else {
// Handle other response controls (if any)
}
}
}
// limit total results.
if (sizeLimit != 0 && nbResult >= sizeLimit) {
cookie = null;
}
// Re-activate paged results
ldapCtx.setRequestControls(new Control[] { new PagedResultsControl(
pageSize, cookie, Control.CRITICAL) });
} while (cookie != null);
} catch (IOException e1) {
logger.error("Can not set pagination control");
} catch (LimitExceededException e) {
logger.error("Limit exceeded (" + String.valueOf(sizeLimit)
+ ") : " + e.getMessage());
} catch (NameNotFoundException nnfe) {
logger.info("While evaluating getDnList, " + base
+ " seems to be inexistent !");
} catch (CommunicationException e) {
Hashtable<?, ?> env = ldapCtx.getEnvironment();
Control[] controls = ldapCtx.getConnectControls();
ldapCtx.close();
ldapCtx = new InitialLdapContext(env, controls);
}
// Re-activate paged results
ldapCtx.setRequestControls(new Control[] {});
return cList;
}
private List<String> getDnListNoPagination(LdapContext ldapCtx,
String base, String filter, int scope) throws NamingException {
List<String> cList = new ArrayList<String>();
SearchControls scs = new SearchControls();
scs.setSearchScope(scope);
scs.setDerefLinkFlag(true);
if (sizeLimit != 0)
scs.setCountLimit(sizeLimit);
try {
NamingEnumeration<SearchResult> ne = ldapCtx.search(base, filter,
scs);
while (ne.hasMore()) {
String dn = ne.next().getName();
if (base.length() > 0) {
dn += "," + base;
}
cList.add(dn);
}
} catch (NameNotFoundException nnfe) {
logger.info("While evaluating getDnList, " + base
+ " seems to be inexistent !");
} catch (LimitExceededException e) {
logger.error("Limit exceeded (" + String.valueOf(sizeLimit)
+ ") : " + e.getMessage());
} catch (CommunicationException e) {
Hashtable<?, ?> env = ldapCtx.getEnvironment();
Control[] controls = ldapCtx.getConnectControls();
ldapCtx.close();
ldapCtx = new InitialLdapContext(env, controls);
}
return cList;
}
}