/*
 *  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.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(password != null && "".equals(password.trim())) {
            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;
    }
}
@@ -1152,24 +1152,69 @@
 dapContext;%0A
+import org.apache.commons.lang3.StringUtils;%0A
 import org.a
@@ -3677,37 +3677,27 @@
  if(
-password != null && %22%22.equals
+StringUtils.isBlank
 (pas
@@ -3705,15 +3705,8 @@
 word
-.trim()
 )) %7B

Use StringUtils.isBlank() like dizzzz advised