package com.hwlcn.security.realm.ldap;
import com.hwlcn.security.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class JndiLdapContextFactory implements LdapContextFactory {
protected static final String SUN_CONNECTION_POOLING_PROPERTY = "com.sun.jndi.ldap.connect.pool";
protected static final String DEFAULT_CONTEXT_FACTORY_CLASS_NAME = "com.sun.jndi.ldap.LdapCtxFactory";
protected static final String SIMPLE_AUTHENTICATION_MECHANISM_NAME = "simple";
protected static final String DEFAULT_REFERRAL = "follow";
private static final Logger log = LoggerFactory.getLogger(JndiLdapContextFactory.class);
private Map<String, Object> environment;
private boolean poolingEnabled;
private String systemPassword;
private String systemUsername;
public JndiLdapContextFactory() {
this.environment = new HashMap<String, Object>();
setContextFactoryClassName(DEFAULT_CONTEXT_FACTORY_CLASS_NAME);
setReferral(DEFAULT_REFERRAL);
poolingEnabled = true;
}
public void setAuthenticationMechanism(String authenticationMechanism) {
setEnvironmentProperty(Context.SECURITY_AUTHENTICATION, authenticationMechanism);
}
public String getAuthenticationMechanism() {
return (String) getEnvironmentProperty(Context.SECURITY_AUTHENTICATION);
}
public void setContextFactoryClassName(String contextFactoryClassName) {
setEnvironmentProperty(Context.INITIAL_CONTEXT_FACTORY, contextFactoryClassName);
}
public String getContextFactoryClassName() {
return (String) getEnvironmentProperty(Context.INITIAL_CONTEXT_FACTORY);
}
public Map getEnvironment() {
return this.environment;
}
@SuppressWarnings({"unchecked"})
public void setEnvironment(Map env) {
this.environment = env;
}
private Object getEnvironmentProperty(String name) {
return this.environment.get(name);
}
private void setEnvironmentProperty(String name, String value) {
if (StringUtils.hasText(value)) {
this.environment.put(name, value);
} else {
this.environment.remove(name);
}
}
public boolean isPoolingEnabled() {
return poolingEnabled;
}
public void setPoolingEnabled(boolean poolingEnabled) {
this.poolingEnabled = poolingEnabled;
}
public void setReferral(String referral) {
setEnvironmentProperty(Context.REFERRAL, referral);
}
public String getReferral() {
return (String) getEnvironmentProperty(Context.REFERRAL);
}
public void setUrl(String url) {
setEnvironmentProperty(Context.PROVIDER_URL, url);
}
public String getUrl() {
return (String) getEnvironmentProperty(Context.PROVIDER_URL);
}
public void setSystemPassword(String systemPassword) {
this.systemPassword = systemPassword;
}
public String getSystemPassword() {
return this.systemPassword;
}
public void setSystemUsername(String systemUsername) {
this.systemUsername = systemUsername;
}
public String getSystemUsername() {
return systemUsername;
}
public LdapContext getSystemLdapContext() throws NamingException {
return getLdapContext((Object) getSystemUsername(), getSystemPassword());
}
protected boolean isPoolingConnections(Object principal) {
return isPoolingEnabled() && principal != null && principal.equals(getSystemUsername());
}
public LdapContext getLdapContext(Object principal, Object credentials) throws NamingException,
IllegalStateException {
String url = getUrl();
if (url == null) {
throw new IllegalStateException("An LDAP URL must be specified of the form ldap://<hostname>:<port>");
}
Hashtable<String, Object> env = new Hashtable<String, Object>(this.environment);
Object authcMech = getAuthenticationMechanism();
if (authcMech == null && (principal != null || credentials != null)) {
env.put(Context.SECURITY_AUTHENTICATION, SIMPLE_AUTHENTICATION_MECHANISM_NAME);
}
if (principal != null) {
env.put(Context.SECURITY_PRINCIPAL, principal);
}
if (credentials != null) {
env.put(Context.SECURITY_CREDENTIALS, credentials);
}
boolean pooling = isPoolingConnections(principal);
if (pooling) {
env.put(SUN_CONNECTION_POOLING_PROPERTY, "true");
}
if (log.isDebugEnabled()) {
log.debug("Initializing LDAP context using URL [{}] and principal [{}] with pooling {}",
new Object[]{url, principal, (pooling ? "enabled" : "disabled")});
}
return createLdapContext(env);
}
protected LdapContext createLdapContext(Hashtable env) throws NamingException {
return new InitialLdapContext(env, null);
}
}