org.exist.security.realm.ldap.LdapContextFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.exist.security.realm.ldap.LdapContextFactory.java

Source

/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2010 The eXist Project
 *  http://exist-db.org
 *  
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *  
 *  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 Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *  
 *  $Id$
 */
package org.exist.security.realm.ldap;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.exist.config.Configurable;
import org.exist.config.Configuration;
import org.exist.config.Configurator;
import org.exist.config.annotation.ConfigurationClass;
import org.exist.config.annotation.ConfigurationFieldAsElement;

/**
 * @author <a href="mailto:shabanovd@gmail.com">Dmitriy Shabanov</a>
 * 
 */
@ConfigurationClass("context")
public class LdapContextFactory implements Configurable {

    protected final static Logger LOG = Logger.getLogger(LdapContextFactory.class);

    protected static final String SUN_CONNECTION_POOLING_PROPERTY = "com.sun.jndi.ldap.connect.pool";

    @ConfigurationFieldAsElement("authentication")
    protected String authentication = "simple";

    @ConfigurationFieldAsElement("use-ssl")
    private final boolean ssl = false;

    @ConfigurationFieldAsElement("principal-pattern")
    protected String principalPattern = null;
    protected MessageFormat principalPatternFormat;

    @ConfigurationFieldAsElement("url")
    protected String url = null;

    @ConfigurationFieldAsElement("domain")
    protected String domain = null;

    protected String contextFactoryClassName = "com.sun.jndi.ldap.LdapCtxFactory";

    protected String systemUsername = null;

    protected String systemPassword = null;

    private boolean usePooling = true;

    private Configuration configuration = null;

    @ConfigurationFieldAsElement("search")
    private LDAPSearchContext search;

    @ConfigurationFieldAsElement("transformation")
    private LDAPTransformationContext realmTransformation;

    public LdapContextFactory(final Configuration config) {
        configuration = Configurator.configure(this, config);
        if (principalPattern != null) {
            principalPatternFormat = new MessageFormat(principalPattern);
        }
    }

    public LdapContext getSystemLdapContext() throws NamingException {
        return getLdapContext(systemUsername, systemPassword);
    }

    public LdapContext getLdapContext(final String username, final String password) throws NamingException {
        return getLdapContext(username, password, null);
    }

    public LdapContext getLdapContext(String username, final String password,
            final Map<String, Object> additionalEnv) throws NamingException {

        if (url == null) {
            throw new IllegalStateException("An LDAP URL must be specified of the form ldap://<hostname>:<port>");
        }

        if (StringUtils.isBlank(password)) {
            throw new IllegalStateException("Password for LDAP authentication may not be empty.");
        }

        if (username != null && principalPattern != null) {
            username = principalPatternFormat.format(new String[] { username });
        }

        final Hashtable<String, Object> env = new Hashtable<String, Object>();

        env.put(Context.SECURITY_AUTHENTICATION, authentication);
        if (ssl) {
            env.put(Context.SECURITY_PROTOCOL, "ssl");
        }

        if (username != null) {
            env.put(Context.SECURITY_PRINCIPAL, username);
        }

        if (password != null) {
            env.put(Context.SECURITY_CREDENTIALS, password);
        }

        env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactoryClassName);
        env.put(Context.PROVIDER_URL, url);

        //Absolutely nessecary for working with Active Directory
        env.put("java.naming.ldap.attributes.binary", "objectSid");

        // the following is helpful in debugging errors
        //env.put("com.sun.jndi.ldap.trace.ber", System.err);

        // Only pool connections for system contexts
        if (usePooling && username != null && username.equals(systemUsername)) {
            // Enable connection pooling
            env.put(SUN_CONNECTION_POOLING_PROPERTY, "true");
        }

        if (additionalEnv != null) {
            env.putAll(additionalEnv);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("Initializing LDAP context using URL [" + url + "] and username [" + username + "] "
                    + "with pooling [" + (usePooling ? "enabled" : "disabled") + "]");
        }

        return new InitialLdapContext(env, null);
    }

    public LDAPSearchContext getSearch() {
        return search;
    }

    public LDAPTransformationContext getTransformationContext() {
        return realmTransformation;
    }

    public String getDomain() {
        return domain;
    }

    // configurable methods
    @Override
    public boolean isConfigured() {
        return (configuration != null);
    }

    @Override
    public Configuration getConfiguration() {
        return configuration;
    }
}