All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.ldap.pool.DelegatingContext Maven / Gradle / Ivy

There is a newer version: 3.2.4
Show newest version
/*
 * Copyright 2005-2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.ldap.pool;

import org.apache.commons.pool.KeyedObjectPool;
import org.springframework.ldap.pool.factory.PoolingContextSource;
import org.springframework.util.Assert;

import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import java.util.Hashtable;

/**
 * Used by {@link PoolingContextSource} to wrap a {@link Context}, delegating most methods
 * to the underlying context, retains a reference to the pool the context was checked out
 * from and returns itself to the pool when {@link #close()} is called.
 * 
 * @author Eric Dalquist
 */
public class DelegatingContext implements Context {
    private KeyedObjectPool keyedObjectPool;
    private Context delegateContext;
    private final DirContextType dirContextType;
    

    /**
     * Create a new delegating context for the specified pool, context and context type.
     * 
     * @param keyedObjectPool The pool the delegate context was checked out from.
     * @param delegateContext The context to delegate operations to.
     * @param dirContextType The type of context, used as a key for the pool.
     * @throws IllegalArgumentException if any of the arguments are null
     */
    public DelegatingContext(KeyedObjectPool keyedObjectPool, Context delegateContext, DirContextType dirContextType) {
        Assert.notNull(keyedObjectPool, "keyedObjectPool may not be null");
        Assert.notNull(delegateContext, "delegateContext may not be null");
        Assert.notNull(dirContextType, "dirContextType may not be null");
        
        this.keyedObjectPool = keyedObjectPool;
        this.delegateContext = delegateContext;
        this.dirContextType = dirContextType;
    }
    
    
    //***** Helper Methods *****//
    
    /**
     * @return The direct delegate for this context proxy
     */
    public Context getDelegateContext() {
        return this.delegateContext;
    }
    
    /**
     * Recursivley inspect delegates until a non-delegating context is found.
     * 
     * @return The innermost (real) Context that is being delegated to.
     */
    public Context getInnermostDelegateContext() {
        final Context delegateContext = this.getDelegateContext();
        
        if (delegateContext instanceof DelegatingContext) {
            return ((DelegatingContext)delegateContext).getInnermostDelegateContext();
        }

        return delegateContext;
    }
    
    /**
     * @throws NamingException If the delegate is null, {@link #close()} has been called.
     */
    protected void assertOpen() throws NamingException {
        if (this.delegateContext == null) {
            throw new NamingException("Context is closed.");
        }
    }

    
    //***** Object methods *****//

    /**
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Context)) {
            return false;
        }
        
        final Context thisContext = this.getInnermostDelegateContext();
        Context otherContext = (Context)obj;
        if (otherContext instanceof DelegatingContext) {
            otherContext = ((DelegatingContext)otherContext).getInnermostDelegateContext();
        }
        
        return thisContext == otherContext || (thisContext != null && thisContext.equals(otherContext));
    }

    /**
     * @see java.lang.Object#hashCode()
     */
    public int hashCode() {
        final Context context = this.getInnermostDelegateContext();
        return (context != null ? context.hashCode() : 0);
    }

    /**
     * @see java.lang.Object#toString()
     */
    public String toString() {
        final Context context = this.getInnermostDelegateContext();
        return (context != null ? context.toString() : "Context is closed");
    }
    
    
    //***** Context Interface Delegates *****//

    /**
     * @see javax.naming.Context#addToEnvironment(java.lang.String, java.lang.Object)
     */
    public Object addToEnvironment(String propName, Object propVal) throws NamingException {
        throw new UnsupportedOperationException("Cannot call addToEnvironment on a pooled context");
    }

    /**
     * @see javax.naming.Context#bind(javax.naming.Name, java.lang.Object)
     */
    public void bind(Name name, Object obj) throws NamingException {
        this.assertOpen();
        this.getDelegateContext().bind(name, obj);
    }

    /**
     * @see javax.naming.Context#bind(java.lang.String, java.lang.Object)
     */
    public void bind(String name, Object obj) throws NamingException {
        this.assertOpen();
        this.getDelegateContext().bind(name, obj);
    }

    /**
     * @see javax.naming.Context#close()
     */
    public void close() throws NamingException {
        final Context context = this.getInnermostDelegateContext();
        if (context == null) {
            return;
        }
        
        //Get a local reference so the member can be nulled earlier
        this.delegateContext = null;

        //Return the object to the Pool and then null the pool reference
        try {
            boolean valid = true;

            if (context instanceof FailureAwareContext) {
                FailureAwareContext failureAwareContext = (FailureAwareContext) context;
                if(failureAwareContext.hasFailed()) {
                    valid = false;
                }
            }

            if (valid) {
                this.keyedObjectPool.returnObject(this.dirContextType, context);
            } else {
                this.keyedObjectPool.invalidateObject(this.dirContextType, context);
            }
        }
        catch (Exception e) {
            final NamingException namingException = new NamingException("Failed to return delegate Context to pool.");
            namingException.setRootCause(e);
            throw namingException;
        }
        finally {
            this.keyedObjectPool = null;
        }
    }

    /**
     * @see javax.naming.Context#composeName(javax.naming.Name, javax.naming.Name)
     */
    public Name composeName(Name name, Name prefix) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().composeName(name, prefix);
    }

    /**
     * @see javax.naming.Context#composeName(java.lang.String, java.lang.String)
     */
    public String composeName(String name, String prefix) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().composeName(name, prefix);
    }

    /**
     * @see javax.naming.Context#createSubcontext(javax.naming.Name)
     */
    public Context createSubcontext(Name name) throws NamingException {
        throw new UnsupportedOperationException("Cannot call createSubcontext on a pooled context");
    }

    /**
     * @see javax.naming.Context#createSubcontext(java.lang.String)
     */
    public Context createSubcontext(String name) throws NamingException {
        throw new UnsupportedOperationException("Cannot call createSubcontext on a pooled context");
    }

    /**
     * @see javax.naming.Context#destroySubcontext(javax.naming.Name)
     */
    public void destroySubcontext(Name name) throws NamingException {
        throw new UnsupportedOperationException("Cannot call destroySubcontext on a pooled context");
    }

    /**
     * @see javax.naming.Context#destroySubcontext(java.lang.String)
     */
    public void destroySubcontext(String name) throws NamingException {
        throw new UnsupportedOperationException("Cannot call destroySubcontext on a pooled context");
    }

    /**
     * @see javax.naming.Context#getEnvironment()
     */
    public Hashtable getEnvironment() throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().getEnvironment();
    }

    /**
     * @see javax.naming.Context#getNameInNamespace()
     */
    public String getNameInNamespace() throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().getNameInNamespace();
    }

    /**
     * @see javax.naming.Context#getNameParser(javax.naming.Name)
     */
    public NameParser getNameParser(Name name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().getNameParser(name);
    }

    /**
     * @see javax.naming.Context#getNameParser(java.lang.String)
     */
    public NameParser getNameParser(String name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().getNameParser(name);
    }

    /**
     * @see javax.naming.Context#list(javax.naming.Name)
     */
    public NamingEnumeration list(Name name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().list(name);
    }

    /**
     * @see javax.naming.Context#list(java.lang.String)
     */
    public NamingEnumeration list(String name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().list(name);
    }

    /**
     * @see javax.naming.Context#listBindings(javax.naming.Name)
     */
    public NamingEnumeration listBindings(Name name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().listBindings(name);
    }

    /**
     * @see javax.naming.Context#listBindings(java.lang.String)
     */
    public NamingEnumeration listBindings(String name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().listBindings(name);
    }

    /**
     * @see javax.naming.Context#lookup(javax.naming.Name)
     */
    public Object lookup(Name name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().lookup(name);
    }

    /**
     * @see javax.naming.Context#lookup(java.lang.String)
     */
    public Object lookup(String name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().lookup(name);
    }

    /**
     * @see javax.naming.Context#lookupLink(javax.naming.Name)
     */
    public Object lookupLink(Name name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().lookupLink(name);
    }

    /**
     * @see javax.naming.Context#lookupLink(java.lang.String)
     */
    public Object lookupLink(String name) throws NamingException {
        this.assertOpen();
        return this.getDelegateContext().lookupLink(name);
    }

    /**
     * @see javax.naming.Context#rebind(javax.naming.Name, java.lang.Object)
     */
    public void rebind(Name name, Object obj) throws NamingException {
        this.assertOpen();
        this.getDelegateContext().rebind(name, obj);
    }

    /**
     * @see javax.naming.Context#rebind(java.lang.String, java.lang.Object)
     */
    public void rebind(String name, Object obj) throws NamingException {
        this.assertOpen();
        this.getDelegateContext().rebind(name, obj);
    }

    /**
     * @see javax.naming.Context#removeFromEnvironment(java.lang.String)
     */
    public Object removeFromEnvironment(String propName) throws NamingException {
        throw new UnsupportedOperationException("Cannot call removeFromEnvironment on a pooled context");
    }

    /**
     * @see javax.naming.Context#rename(javax.naming.Name, javax.naming.Name)
     */
    public void rename(Name oldName, Name newName) throws NamingException {
        this.assertOpen();
        this.getDelegateContext().rename(oldName, newName);
    }

    /**
     * @see javax.naming.Context#rename(java.lang.String, java.lang.String)
     */
    public void rename(String oldName, String newName) throws NamingException {
        this.assertOpen();
        this.getDelegateContext().rename(oldName, newName);
    }

    /**
     * @see javax.naming.Context#unbind(javax.naming.Name)
     */
    public void unbind(Name name) throws NamingException {
        this.assertOpen();
        this.getDelegateContext().unbind(name);
    }

    /**
     * @see javax.naming.Context#unbind(java.lang.String)
     */
    public void unbind(String name) throws NamingException {
        this.assertOpen();
        this.getDelegateContext().unbind(name);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy