package com.openedit.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.PartialResultException;
import javax.naming.SizeLimitExceededException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openedit.data.BaseData;
import com.openedit.OpenEditException;
import com.openedit.hittracker.HitTracker;
import com.openedit.hittracker.ListHitTracker;
import com.openedit.users.User;
import com.openedit.users.UserManagerException;
public class LDAP
{
private static final Log log = LogFactory.getLog(LDAP.class);
protected Properties fieldEnvironment;
protected DirContext fieldContext;
protected String fieldServerName;
protected String fieldDomain;
protected int fieldMaxLdapResults;
public LDAP()
{
if (getServerName() != null)
{
init(getServerName());
}
}
public LDAP(String inServerName)
{
init(inServerName);
}
public void setServerName(String inServerName)
{
init(inServerName);
fieldServerName = inServerName;
}
public String getServerName()
{
return fieldServerName;
}
protected Properties getEnvironment()
{
if (fieldEnvironment == null)
{
fieldEnvironment = new Properties();
}
return fieldEnvironment;
}
protected void setEnvironment(Properties inEnvironment)
{
fieldEnvironment = inEnvironment;
}
public void init(String inServerName)
{
Properties env = getEnvironment();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
if (!inServerName.startsWith("ldap://"))
{
inServerName = "ldap://" + inServerName + "/";
}
env.put(Context.PROVIDER_URL, inServerName);
log.info("[LDAP] Connecting to " + inServerName);
}
public void authenticate(User inUser, String inPassword)
{
StringBuffer dnbuffer = new StringBuffer();
String base = (String) inUser.getProperty("ldap_prefix");
if (base != null)
{
dnbuffer.append(base);
}
dnbuffer.append(inUser.getUserName());
String post = (String) inUser.getProperty("ldap_postfix");
if (post != null)
{
//dnbuffer.append(",");
dnbuffer.append(post);
}
//uid=%s,ou=People,dc=company,dc=com
// String base = "ou=People,dc=example,dc=com";
// String dn = "uid=" + inUser.getUserName() + "," + base;
getEnvironment().put(Context.SECURITY_PRINCIPAL, dnbuffer.toString());
getEnvironment().put(Context.SECURITY_CREDENTIALS, inPassword);
}
public DirContext getContext()
{
return fieldContext;
}
public boolean connect() throws UserManagerException
{
if (isConnected())
{
return false;
}
try
{
// obtain initial directory context using the environment
fieldContext = new InitialDirContext(getEnvironment());
// now, create the root context, which is just a subcontext
// of this initial directory context.
// ctx.createSubcontext( rootContext );
} catch (NameAlreadyBoundException nabe)
{
log.error("LDAP has already been bound!");
return false;
} catch (Exception e)
{
log.error(e);
return false;
}
return true;
}
public void disconnect()
{
if (isConnected())
{
try
{
getContext().close();
fieldContext = null;
} catch (NamingException e)
{
e.printStackTrace();
}
}
}
public boolean isConnected()
{
if (getContext() != null)
{
try
{
getContext().lookup("");
return true;
} catch (NamingException ne)
{
return false;
}
}
return false;
}
/**
* These searches do not take in a list of attributes
* @param domain
* @param searchby
* @param value
* @return
*/
public HitTracker search(String searchby, String value)
{
return search(searchby, null, value);
}
public HitTracker search(String searchby, String operation, String value)
{
String query = null;
if(operation != null && operation.equals("substring"))
{
query = "(" + searchby + "=" + value + "*)";
}
else
{
query = "(" + searchby + "=" + value + ")";
}
return search(getDomain(), query, getMaxLdapResults());
}
/**
* Gets ALL the known Attributes
* @param domain
* @param query
* @param maxresults: maximum results returned. Use 1 for lookups.
* @return
*/
protected HitTracker search(String query)
{
return search( getDomain(), query, getMaxLdapResults());
}
protected HitTracker search(String domain, String query, int maxresults)
{
connect();
if (domain == null)
{
domain = "";
}
SearchControls ctrl = new SearchControls();
ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE);
ctrl.setCountLimit(maxresults);
NamingEnumeration enumeration;
ListHitTracker results = new ListHitTracker(); //list of HashMaps
try
{
enumeration = getContext().search(domain, query, ctrl);
while (enumeration.hasMore())
{
SearchResult result = (SearchResult) enumeration.next();
Attributes attribs = result.getAttributes();
NamingEnumeration values = attribs.getAll();
Map row = new HashMap();
while( values.hasMore())
{
BasicAttribute basic = (BasicAttribute) values.next();
String value = basic.get().toString();
row.put(basic.getID(), value);
}
results.add(new BaseData(row));
if( results.size() == maxresults )
{
break;
}
}
log.info("[LDAP] Searched for " + query + " in domain " + domain + " found " + results.size());
}
catch (SizeLimitExceededException e)
{
log.error(e);
}
catch (PartialResultException e)
{
//more than 1
log.error(e);
}
catch (NamingException e)
{
throw new OpenEditException(e);
}
return results;
}
public String getDomain()
{
return fieldDomain;
}
public void setDomain(String inDomain)
{
fieldDomain = inDomain;
}
public int getMaxLdapResults()
{
return fieldMaxLdapResults;
}
public void setMaxLdapResults(int inMaxLdapResults)
{
fieldMaxLdapResults = inMaxLdapResults;
}
}