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

com.addc.jndi.java.JavaContext Maven / Gradle / Ivy

package com.addc.jndi.java;

import java.text.MessageFormat;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.ContextNotEmptyException;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NotContextException;

/**
 * The JavaContext supplies a context within the java: name space
 */
@SuppressWarnings({ "PMD.LooseCoupling", "PMD.TooManyMethods" })
public class JavaContext extends AbstractJavaContext {
    private static final String EMPTY_NAME= "Cannot bind to an empty name.";
    private static final String ALREADY_BOUND= "{0}/{1} is already bound.";
    private final Map bindings= new ConcurrentHashMap<>();
    private final JavaContext parent;

    /**
     * The NextContext holds a reference to the next context along with the rest
     * of the name
     */
    private static class NextContext {
        public JavaContext context;
        public Name name;

        /**
         * Create a new NextContext
         */
        public NextContext() {
            super();
        }
    }

    /**
     * Create a new JavaContext
     * 
     * @param env
     *            The environment
     * @param nameInNamespace
     *            The name within the name space
     */
    public JavaContext(Hashtable env, String nameInNamespace, JavaContext parent) {
        super(env, nameInNamespace);
        this.parent= parent;
    }

    /**
     * Get the bindings
     * 
     * @return the bindings
     */
    Map getBindings() {
        return bindings;
    }

    @Override
    public Object lookup(Name name) throws NamingException {
        if (name.isEmpty()) {
            return this;
        }
        if (name.size() > 1) {
            NextContext next= getNextContext(name);
            return next.context.lookup(next.name);
        }
        if (!bindings.containsKey(name)) {
            NameNotFoundException nnfe= new NameNotFoundException(
                    MessageFormat.format("{0}/{1} is not bound.", nameInNamespace, name));
            nnfe.setRemainingName(name);
            throw nnfe;
        }
        return bindings.get(name).getValue();
    }

    @Override
    public void bind(Name name, Object obj) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException(EMPTY_NAME);
        }
        if (name.size() > 1) {
            NextContext next= getNextContext(name);
            next.context.bind(next.name, obj);
            return;
        }
        NameEntry entry= bindings.get(name);
        if (entry == null) {
            if (obj instanceof Context) {
                entry= new NameEntry(name, obj, EntryType.Context);
            } else {
                entry= new NameEntry(name, obj, EntryType.Object);
            }
            bindings.put(name, entry);
        } else {
            throw new NameAlreadyBoundException(MessageFormat.format(ALREADY_BOUND, nameInNamespace, name));
        }

    }

    @Override
    public void rebind(Name name, Object obj) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException(EMPTY_NAME);
        }
        if (name.size() > 1) {
            NextContext next= getNextContext(name);
            next.context.rebind(next.name, obj);
            return;
        }
        NameEntry entry;
        if (obj instanceof Context) {
            entry= new NameEntry(name, obj, EntryType.Context);
        } else {
            entry= new NameEntry(name, obj, EntryType.Object);
        }
        bindings.put(name, entry);
    }

    @Override
    public void unbind(Name name) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException("Cannot unbind an empty name.");
        }
        if (name.size() > 1) {
            NextContext next= getNextContext(name);
            next.context.unbind(next.name);
            return;
        }
        bindings.remove(name);
    }

    @Override
    public void rename(Name oldName, Name newName) throws NamingException {
        synchronized (mutex) {
            Object value= lookup(oldName);
            bind(newName, value);
            unbind(oldName);
        }
    }

    @Override
    public NamingEnumeration list(Name name) throws NamingException {
        if (name.size() > 0) {
            NextContext next= getNextContext(name);
            return next.context.list(next.name);
        }
        return doListClassPair();
    }

    @Override
    public NamingEnumeration listBindings(Name name) throws NamingException {
        if (name.size() > 0) {
            NextContext next= getNextContext(name);
            return next.context.listBindings(next.name);
        }
        return doListBindings();
    }

    @Override
    public void destroySubcontext(Name name) throws NamingException {
        if (name.size() > 1) {
            NextContext next= getNextContext(name);
            next.context.destroySubcontext(next.name);
            return;
        }
        synchronized (mutex) {
            NameEntry entry= bindings.get(name);
            if (entry != null) {
                if (entry.getType() != EntryType.Context) {
                    throw new NotContextException("Context expected at " + name);
                }
                JavaContext context= (JavaContext) entry.getValue();
                if (context.getBindings().isEmpty()) {
                    bindings.remove(name);
                } else {
                    throw new ContextNotEmptyException(
                            MessageFormat.format("The Context at {0}/{1} is not empty.", nameInNamespace, name));
                }
            }
        }
    }

    @Override
    public Context createSubcontext(Name name) throws NamingException {
        if (name.size() > 1) {
            NextContext next= getNextContext(name);
            return next.context.createSubcontext(next.name);
        }
        if (bindings.containsKey(name)) {
            throw new NameAlreadyBoundException(MessageFormat.format(ALREADY_BOUND, nameInNamespace, name));
        }
        JavaContext context= new JavaContext(env, nameInNamespace + "/" + name, this);
        NameEntry entry= new NameEntry(name, context, EntryType.Context);
        bindings.put(name, entry);
        return context;
    }

    @Override
    public Object lookupLink(Name name) throws NamingException {
        return lookup(name);
    }

    @Override
    public NameParser getNameParser(Name name) throws NamingException {
        return new JavaNameParser();
    }

    @Override
    public Name composeName(Name name, Name prefix) throws NamingException {
        Name prefx= (Name) prefix.clone();
        return prefx.addAll(name);
    }

    @Override
    public void close() throws NamingException {
        // Nothing to do
    }

    @Override
    public String toString() {
        return "JavaContext [nameInNamespace=" + nameInNamespace + "]";
    }

    private NamingEnumeration doListClassPair() {
        List vector= new LinkedList<>();
        synchronized (mutex) {
            for (Entry entry : bindings.entrySet()) {
                vector.add(new NameClassPair(entry.getKey().toString(), entry.getValue().getClass().getName()));
            }
        }
        return new ClassPairEnumeration(vector);
    }

    private NamingEnumeration doListBindings() {
        List vector= new LinkedList<>();
        synchronized (mutex) {
            for (Entry entry : bindings.entrySet()) {
                vector.add(new Binding(entry.getKey().toString(), entry.getValue()));
            }
        }
        return new BindingEnumeration(vector);
    }

    private NextContext getNextContext(Name name) throws NamingException {
        Name first= name.getPrefix(1);
        if ("/".equals(first.toString())) {
            NextContext next= new NextContext();
            next.context= getRoot();
            next.name= name.getSuffix(1);
            return next;
        }
        NameEntry entry= bindings.get(first);
        if (entry == null) {
            NameNotFoundException nnfe= new NameNotFoundException(
                    MessageFormat.format("{0}/{1} is not bound.", nameInNamespace, name.getPrefix(1)));
            nnfe.setRemainingName(name);
            throw nnfe;
        }
        if (entry.getType() != EntryType.Context) {
            throw new NotContextException(MessageFormat.format("{0}/{1} is not a Context.", nameInNamespace, name));
        }
        NextContext next= new NextContext();
        next.context= (JavaContext) entry.getValue();
        next.name= name.getSuffix(1);
        return next;
    }

    /**
     * Recurse up the parent nodes to the root
     *
     * @return The root context
     */
    JavaContext getRoot() {
        if (parent == null) {
            return this;
        }
        return parent.getRoot();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy