/**
* Copyright (c) 2008, MTV Networks
*/
package com.mtvi.plateng.hudson.ldap;
import hudson.model.User;
import hudson.tasks.MailAddressResolver;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
/**
* Implementation of hudson.tasks.MailAddressResolver that looks up the email
* address for a user based on information in an LDAP directory.
*
* @author justinedelson
*
*/
public class LdapMailAddressResolver extends MailAddressResolver {
/**
* A logger object.
*/
private static final Logger LOGGER = Logger.getLogger("hudson."
+ LdapMailAddressResolver.class.getName());
/**
* Configuration object encapsulating how to connect to the LDAP server.
*/
private Configuration configuration;
/**
* Build an instance wrapping a Configuration object.
*
* @param config the Configuration object
*/
public LdapMailAddressResolver(Configuration config) {
configuration = config;
if (!configuration.isValid()) {
LOGGER.warning("Provided configuration isn't valid. Check for missing elements.");
}
}
/**
* {@inheritDoc}
*/
@Override
public String findMailAddressFor(User user) {
return findMailAddressFor(user.getDisplayName());
}
/**
* Look up the email address for a user in the directory.
*
* @param userName the user's username, generally corresponds to the uid
* attribute.
* @return the corresponding email address from the directory, or null if
* none can be found.
*/
protected String findMailAddressFor(String userName) {
if (configuration.isValid()) {
try {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, configuration
.getInitialContextFactoryName());
env.put(Context.PROVIDER_URL, configuration.getServer());
if (configuration.isBindCredentialsProvided()) {
LOGGER.log(Level.INFO, "Using provided credentials for binding to LDAP server");
env.put(Context.SECURITY_PRINCIPAL, configuration.getBindDN());
env.put(Context.SECURITY_CREDENTIALS, configuration.getBindPassword());
}
DirContext ctx = new InitialDirContext(env);
if (configuration.isPerformSearch()) {
return performSearch(ctx, userName);
} else {
return performLookup(ctx, userName);
}
} catch (NamingException e) {
LOGGER.log(Level.SEVERE, "Unable to run LDAP query", e);
}
}
return null;
}
private String performLookup(DirContext ctx, String userName) throws NamingException {
String emailAddress = null;
String dn = configuration.makeUserDN(userName);
LOGGER.log(Level.INFO, String.format("Looking up attributes for DN %s", dn));
Attributes attrs = ctx
.getAttributes(dn, new String[] { configuration.getEmailAttribute() });
Attribute attr = attrs.get(configuration.getEmailAttribute());
if (attr != null) {
emailAddress = (String) attr.get();
LOGGER.log(Level.INFO, String.format("Found mail attribute %s for userName %s",
emailAddress, userName));
} else {
LOGGER.log(Level.INFO, String.format("No mail attribute found for userName %s",
userName));
}
return emailAddress;
}
private String performSearch(DirContext ctx, String userName) throws NamingException {
String emailAddress = null;
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String filter = String.format("%s=%s", configuration.getSearchAttribute(), userName);
LOGGER.log(Level.INFO, String.format("Performing LDAP search within %s using %s",
configuration.getBaseDN(), filter));
NamingEnumeration<SearchResult> results = ctx.search(configuration.getBaseDN(), filter,
controls);
if (results.hasMore()) {
SearchResult result = results.next();
Attribute attr = result.getAttributes().get(configuration.getEmailAttribute());
if (attr != null) {
emailAddress = (String) attr.get();
LOGGER.log(Level.INFO, String.format("Found mail attribute %s for userName %s",
emailAddress, userName));
} else {
LOGGER.log(Level.INFO, String.format("No mail attribute found for userName %s",
userName));
}
} else {
LOGGER.log(Level.INFO, String.format("No results found for filter %s inside baseDN %s",
filter, configuration.getBaseDN()));
}
return emailAddress;
}
}