Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.xbib.groovy.ldap.LDAP Maven / Gradle / Ivy
package org.xbib.groovy.ldap;
import groovy.lang.Closure;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.LdapName;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A wrapper class which provides LDAP functionality to Groovy.
*/
public class LDAP {
private static final Logger logger = Logger.getLogger(LDAP.class.getName());
private static final String DEFAULT_URL = "ldap://localhost:389/";
private final String url;
private final String bindUser;
private final String bindPassword;
private LDAP(String url, String bindUser, String bindPassword) {
this.url = url;
this.bindUser = bindUser;
this.bindPassword = bindPassword;
}
public static LDAP newInstance() {
return new LDAP(DEFAULT_URL, null, null);
}
public static LDAP newInstance(String url) {
return new LDAP(url, null, null);
}
public static LDAP newInstance(String url, String bindUser, String bindPassword) {
return new LDAP(url, bindUser, bindPassword);
}
/**
* LDAP add operation. Adds a new entry to the directory. The attributes have to be provided as a map.
*
* @param dn DN of the entry
* @param attributes attributes of the entry
* @throws NamingException if DN can not be resolved
*/
public void add(final String dn, final Map attributes) throws NamingException {
WithContext action = ctx -> {
BasicAttributes attrs = new BasicAttributes();
for (Map.Entry entry : attributes.entrySet()) {
logger.log(Level.FINE, MessageFormat.format("entry {0} {1}", entry, entry.getValue().getClass()));
Attribute attr = createAttribute(entry.getKey(), entry.getValue());
logger.log(Level.FINE, MessageFormat.format("attr {0} {1}", attr, attr.get().getClass()));
attrs.put(attr);
}
ctx.createSubcontext(dn, attrs);
return null;
};
performWithContext(action);
}
/**
* LDAP delete operation. Deletes an entry from the directory.
*
* @param dn DN of the entry
* @throws NamingException if DN can not be resolved
*/
public void delete(final String dn) throws NamingException {
if (!exists(dn)) {
throw new NameNotFoundException("Entry " + dn + " does not exist!");
}
WithContext action = ctx -> {
ctx.destroySubcontext(dn);
return null;
};
performWithContext(action);
}
/**
* Reads an entry by its DN.
* @param dn distinguished name
* @return object
* @throws NamingException if DN can not be resolved
*/
public Object read(final String dn) throws NamingException {
return performWithContext(ctx -> ctx.lookup(dn));
}
/**
* Check whether an entry with the given DN exists. The method performs a search to check this, which is not so
* efficient than just reading the entry.
* @param dn distinguished name
* @return true if exists
* @throws NamingException if DN can not be resolved
*/
public boolean exists(final String dn) throws NamingException {
WithContext action = ctx -> {
SearchControls sc = new SearchControls();
sc.setSearchScope(SearchControls.OBJECT_SCOPE);
sc.setReturningAttributes(new String[0]);
sc.setReturningObjFlag(false);
try {
ctx.search(dn, "(objectClass=*)", sc);
return true;
} catch (NameNotFoundException e) {
logger.log(Level.FINEST, e.getMessage(), e);
}
return false;
};
return performWithContext(action);
}
/**
* LDAP compare operation.
*
* @param dn Distinguished name of the entry.
* @param assertion attribute assertion.
* @return true is comparison matches
* @throws NamingException if DN can not be resolved
*/
public boolean compare(final String dn, final Map assertion) throws NamingException {
if (assertion.size() != 1) {
throw new IllegalArgumentException("Assertion may only include one attribute");
}
WithContext action = ctx -> {
SearchControls sc = new SearchControls();
sc.setReturningAttributes(new String[0]);
sc.setSearchScope(SearchControls.OBJECT_SCOPE);
sc.setReturningObjFlag(false);
String attrName = assertion.keySet().iterator().next();
String filter = "(" + attrName + "={0})";
Object value = assertion.get(attrName);
NamingEnumeration enumeration = ctx.search(dn, filter, new Object[]{value}, sc);
return enumeration.hasMore();
};
return performWithContext(action);
}
/**
* LDAP modify DN operation.
*
* @param dn Distinguished name of the entry.
* @param newRDN new realtive distinguished name of the entry.
* @param deleteOldRDN if old relative distinguished name should be deleted
* @param newSuperior new superior DN
* @throws NamingException if DN can not be resolved
*/
public void modifyDn(final String dn, final String newRDN, final boolean deleteOldRDN, final String newSuperior)
throws NamingException {
WithContext action = ctx -> {
LdapName source = new LdapName(dn);
LdapName target = new LdapName(newSuperior);
target.add(newRDN);
ctx.addToEnvironment("java.naming.ldap.deleteRDN", Boolean.toString(deleteOldRDN));
ctx.rename(source, target);
return null;
};
performWithContext(action);
}
public void eachEntry(String filter, String base, SearchScope scope, Closure closure) throws NamingException {
eachEntry(new Search(base, scope, filter), closure);
}
public void eachEntry(Map searchParams, Closure closure) throws NamingException {
eachEntry(new Search(searchParams), closure);
}
public void eachEntry(String filter, Closure closure) throws NamingException {
eachEntry(filter, "", SearchScope.SUB, closure);
}
public void eachEntry(Search search, Closure closure) throws NamingException {
WithContext action = ctx -> {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(search.getScope().getJndiValue());
ctls.setReturningAttributes(search.getAttrs());
ctls.setReturningObjFlag(true);
NamingEnumeration results = ctx.search(search.getBase(), search.getFilter(), search
.getFilterArgs(), ctls);
while (results != null && results.hasMore()) {
SearchResult sr = results.next();
String dn = sr.getNameInNamespace();
Attributes attrs = sr.getAttributes();
NamingEnumeration extends Attribute> en = attrs.getAll();
Map map = new LinkedHashMap<>();
map.put("dn", dn);
while (en.hasMore()) {
Attribute attr = en.next();
String key = attr.getID();
map.put(key, attr.get(0).toString());
}
closure.call(map);
}
return null;
};
performWithContext(action);
}
public void modify(String dn, String modType, Map attributes) throws NamingException {
modify(dn, ModificationType.valueOf(modType), attributes);
}
public void modify(String dn, ModificationType modType, Map attributes) throws NamingException {
List mods = new ArrayList<>();
for (String key : attributes.keySet()) {
Attribute attr = createAttribute(key, attributes.get(key));
ModificationItem item = new ModificationItem(modType.getJndiValue(), attr);
mods.add(item);
}
ModificationItem[] modItems = mods.toArray(new ModificationItem[mods.size()]);
WithContext action = ctx -> {
ctx.modifyAttributes(dn, modItems);
return null;
};
performWithContext(action);
}
public void modify(String dn, List modificationItem) throws NamingException {
List mods = new ArrayList<>();
for (List pair : modificationItem) {
if (pair.size() != 2) {
throw new IllegalArgumentException("parameter 2 is not a list of pairs");
}
Object oModType = pair.get(0);
ModificationType modType;
if (oModType instanceof ModificationType) {
modType = (ModificationType) oModType;
} else if (oModType instanceof String) {
modType = ModificationType.valueOf((String) oModType);
} else {
throw new IllegalArgumentException("parameter is not o valid ModificationType: " + oModType);
}
if (pair.get(1) instanceof Map) {
@SuppressWarnings("unchecked")
Map attributes = (Map) pair.get(1);
for (String key : attributes.keySet()) {
Attribute attr = createAttribute(key, attributes.get(key));
ModificationItem item = new ModificationItem(modType.getJndiValue(), attr);
mods.add(item);
}
}
}
ModificationItem[] modItems = mods.toArray(new ModificationItem[mods.size()]);
WithContext action = ctx -> {
ctx.modifyAttributes(dn, modItems);
return null;
};
performWithContext(action);
}
public List> search(String filter) throws NamingException {
return search(new Search("", SearchScope.SUB, filter));
}
public List> search(String base, SearchScope scope, String filter) throws NamingException {
return search(new Search(base, scope, filter));
}
public List> search(Map searchParams) throws NamingException {
return search(new Search(searchParams));
}
public List> search(Search search) throws NamingException {
List> result = new ArrayList<>();
WithContext action = ctx -> {
SearchControls sc = new SearchControls();
sc.setSearchScope(search.getScope().getJndiValue());
sc.setReturningAttributes(search.getAttrs());
sc.setReturningObjFlag(true);
sc.setTimeLimit(5000);
NamingEnumeration results =
ctx.search(search.getBase(), search.getFilter(), search.getFilterArgs(), sc);
while (results != null && results.hasMore()) {
SearchResult sr = results.next();
String dn = sr.getNameInNamespace();
Attributes attrs = sr.getAttributes();
NamingEnumeration extends Attribute> en = attrs.getAll();
Map map = new LinkedHashMap<>();
map.put("dn", dn);
while (en.hasMore()) {
Attribute attr = en.next();
String key = attr.getID();
if (attr.size() == 1) {
map.put(key, attr.get());
} else {
List l = new ArrayList<>();
for (int i = 0; i < attr.size(); ++i) {
l.add(attr.get(i));
}
map.put(key, l);
}
}
result.add(map);
}
return null;
};
performWithContext(action);
return result;
}
/**
* Open an LDAP context and perform a given task within this context.
*
* @param parameter type
* @param action action
* @return an action result
* @throws NamingException naming exception
*/
private T performWithContext(WithContext action) throws NamingException {
LdapContext ctx = null;
try {
ctx = new InitialLdapContext(createEnvironment(url, bindUser, bindPassword), null);
return action.perform(ctx);
} finally {
try {
if (ctx != null) {
ctx.close();
}
} catch (NamingException e) {
logger.log(Level.FINEST, e.getMessage(), e);
}
}
}
private static Properties createEnvironment(String url, String bindUser, String bindPassword) {
Properties env = new Properties();
env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.setProperty(Context.PROVIDER_URL, url);
if (bindUser != null) {
env.setProperty(Context.SECURITY_PRINCIPAL, bindUser);
env.setProperty(Context.SECURITY_CREDENTIALS, bindPassword);
}
return env;
}
private static Attribute createAttribute(String name, Object value) {
Attribute attr = new BasicAttribute(name);
if (value instanceof Collection) {
Collection> values = (Collection>) value;
for (Object val : values) {
attr.add(val);
}
} else {
attr.add(value);
}
return attr;
}
}