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

com.sun.enterprise.naming.impl.TransientContext Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2006-2013 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.enterprise.naming.impl;

import javax.naming.*;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;

import static com.sun.enterprise.naming.util.LogFacade.logger;

/**
 * Class to implement multiple level of subcontexts in SerialContext. To use this
 * class a new object of class InitialContext (env) should be instantiated.
 * The env i.e the Environment is initialised with SerialInitContextFactory
 * An example for using this is in /test/subcontext
 */
public class TransientContext implements Context, Serializable {
    Hashtable myEnv;
    private Map bindings = new HashMap();
    static NameParser myParser = new SerialNameParser();

    // Issue 7067: lots of lookup failures in a heavily concurrent client.
    // So add a read/write lock, which allows unlimited concurrent readers,
    // and only imposes a global lock on relatively infrequent updates.
    private static final ReadWriteLock lock = new ReentrantReadWriteLock() ;

    public TransientContext() {
    }

    /**
     * Create a subcontext with the specified name.
     *
     * @return the created subcontext.
     * @throws NamingException if there is a naming exception.
     */
    @Override
    public Context createSubcontext(String name) throws NamingException {
        return drillDownAndCreateSubcontext(name);
    }

    /**
     * Create a subcontext with the specified name.
     *
     * @return the created subcontext.
     * @throws NamingException if there is a naming exception.
     */
    @Override
    public Context createSubcontext(Name name) throws NamingException {
        return createSubcontext(name.toString());
    }

    /**
     * Destroy the subcontext with the specified name.
     *
     * @throws NamingException if there is a naming exception.
     */
    @Override
    public void destroySubcontext(String name) throws NamingException {
        drillDownAndDestroySubcontext(name);
    }

    /**
     * Destroy the subcontext with the specified name.
     *
     * @throws NamingException if there is a naming exception.
     */
    @Override
    public void destroySubcontext(Name name) throws NamingException {
        destroySubcontext(name.toString());
    }

    /**
     * Handles making nested subcontexts
     * i.e. if you want abcd/efg/hij. It will go  subcontext efg in abcd
     * (if not present already - it will create it) and then
     * make subcontext hij
     *
     * @return the created subcontext.
     * @throws NamingException if there is a Naming exception
     */
    private Context drillDownAndCreateSubcontext(String name)
            throws NamingException {
        lock.writeLock().lock() ;
        try {
            Name n = new CompositeName(name);
            if (n.size() <= 1) { // bottom
                if (bindings.containsKey(name)) {
                    throw new NameAlreadyBoundException("Subcontext " +
                            name + " already present");
                }

                TransientContext ctx = null;
                ctx = new TransientContext();
                bindings.put(name, ctx);
                return ctx;
            } else {
                String suffix = n.getSuffix(1).toString();
                Context retCtx, ctx; // the created context
                try {
                    ctx = resolveContext(n.get(0));
                } catch (NameNotFoundException e) {
                    ctx = new TransientContext();
                }
                retCtx = ctx.createSubcontext(suffix);
                bindings.put(n.get(0), ctx);
                return retCtx;
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Handles deleting nested subcontexts
     * i.e. if you want delete abcd/efg/hij. It will go  subcontext efg in abcd
     * it will delete it) and then delete subcontext hij
     *
     * @throws NamingException if there is a naming exception
     */
    private void drillDownAndDestroySubcontext(String name)
            throws NamingException {
        lock.writeLock().lock();
        try {
            Name n = new CompositeName(name);
            if (n.size() < 1) {
                throw new InvalidNameException("Cannot destoy empty subcontext");
            }
            if (n.size() == 1) { // bottom
                if (bindings.containsKey(name)) {
                    bindings.remove(name);
                } else {
                    throw new NameNotFoundException("Subcontext: " + name +
                            " not found");
                }
            } else {
                String suffix = n.getSuffix(1).toString();
                Context ctx; // the context to drill down from
                ctx = resolveContext(n.get(0));
                ctx.destroySubcontext(suffix);
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Lookup the specified name.
     *
     * @return the object or context bound to the name.
     * @throws NamingException          if there is a naming exception.
     * @throws java.rmi.RemoteException if there is an RMI exception.
     */
    @Override
    public Object lookup(String name) throws NamingException {
        lock.readLock().lock() ;
        try {
            Name n = new CompositeName(name);
            if (n.size() < 1) {
                throw new InvalidNameException("Cannot bind empty name");
            }

            if (n.size() == 1) { // bottom
                return doLookup(n.toString());
            } else {
                String suffix = n.getSuffix(1).toString();
                TransientContext ctx = resolveContext(n.get(0));
                return ctx.lookup(suffix);
            }
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * Lookup the specified name.
     *
     * @return the object or context bound to the name.
     * @throws NamingException          if there is a naming exception.
     * @throws java.rmi.RemoteException if there is an RMI exception.
     */
    @Override
    public Object lookup(Name name) throws NamingException {
        return lookup(name.toString());
    }

    /**
     * Lookup the specified name in the current objects hashtable.
     *
     * @return the object or context bound to the name.
     * @throws NamingException          if there is a naming exception.
     * @throws java.rmi.RemoteException if there is an RMI exception.
     */
    private Object doLookup(String name) throws NamingException {
        Object answer = bindings.get(name);
        if (answer == null) {
            throw new NameNotFoundException(name + " not found");
        }
        return answer;
    }

    /**
     * Bind the object to the specified name.
     *
     * @throws NamingException          if there is a naming exception.
     * @throws java.rmi.RemoteException if there is an RMI exception.
     */
    @Override
    public void bind(String name, Object obj) throws NamingException {
        lock.writeLock().lock();
        try {
            Name n = new CompositeName(name);
            if (n.size() < 1) {
                throw new InvalidNameException("Cannot bind empty name");
            }
            if (n.size() == 1) { // bottom
                doBindOrRebind(n.toString(), obj, false);
            } else {
                String suffix = n.getSuffix(1).toString();
                Context ctx;
                try {
                    ctx = resolveContext(n.get(0));
                } catch (NameNotFoundException e) {
                    ctx = createSubcontext(n.get(0));
                }
                ctx.bind(suffix, obj);
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Bind the object to the specified name.
     *
     * @throws NamingException          if there is a naming exception.
     * @throws java.rmi.RemoteException if there is an RMI exception.
     */
    @Override
    public void bind(Name name, Object obj)
            throws NamingException {
        bind(name.toString(), obj);
    }

    /**
     * Finds out if the subcontext specified is present in the current context
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    /* Finds if the name searched for is a type of context or anyother type of 
     * object.
     */
    private TransientContext resolveContext(String s) throws NamingException {
        //TransientContext ctx = (TransientContext) bindings.get(s);
        TransientContext ctx;
        Object obj = bindings.get(s);
        if (obj == null) {
            throw new NameNotFoundException(s);
        }
        if (obj instanceof TransientContext) {
            ctx = (TransientContext) obj;
        } else {
            throw new NameAlreadyBoundException(s);
        }
        return ctx;
    }

    /**
     * Binds or rebinds the object specified by name
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    private void doBindOrRebind(String name, Object obj, boolean rebind)
            throws NamingException {
        if (name.equals("")) {
            throw new InvalidNameException("Cannot bind empty name");
        }
        if (!rebind) {
            if (bindings.get(name) != null) {
                throw new NameAlreadyBoundException(
                        "Use rebind to override");
            }
        }
        bindings.put(name, obj);
    }


    /**
     * Rebinds the object specified by name
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    @Override
    public void rebind(String name, Object obj)
            throws NamingException {
        lock.writeLock().lock();
        try {
            Name n = new CompositeName(name);
            if (n.size() < 1) {
                throw new InvalidNameException("Cannot bind empty name");
            }
            if (n.size() == 1) { // bottom
                doBindOrRebind(n.toString(), obj, true);
            } else {
                String suffix = n.getSuffix(1).toString();
                Context ctx = null;
                try {
                    ctx = resolveContext(n.get(0));
                    ctx.rebind(suffix, obj);
                } catch (NameNotFoundException e) {
                    ctx = createSubcontext(n.get(0));
                    ctx.rebind(suffix, obj);
                }
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Binds or rebinds the object specified by name
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    @Override
    public void rebind(Name name, Object obj)
            throws NamingException {
        rebind(name.toString(), obj);
    }

    /**
     * Unbinds the object specified by name. Traverses down the context tree
     * and unbinds the object if required.
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    private void doUnbind(String name) throws NamingException {
        if (name.equals("")) {
            throw new InvalidNameException("Cannot unbind empty name");
        }
        // After checking javadoc of Context.unbind(),I think we need not throw
        // NameNotFoundException here.
        /*if (bindings.get(name) == null) {
            throw new NameNotFoundException(
                    "Cannot find name to unbind");
        }*/
        bindings.remove(name);
    }

    /**
     * Unbinds the object specified by name. Calls itself recursively to
     * traverse down the context tree and unbind the object.
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    @Override
    public void unbind(String name) throws NamingException {
        lock.writeLock().lock();
        try {
            Name n = new CompositeName(name);
            if (n.size() < 1) {
                throw new InvalidNameException("Cannot unbind empty name");
            }
            if (n.size() == 1) { // bottom
                doUnbind(n.toString());
            } else {
                String suffix = n.getSuffix(1).toString();
                TransientContext ctx = resolveContext(n.get(0));
                ctx.unbind(suffix);
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Unbinds the object specified by name
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    @Override
    public void unbind(Name name)
            throws NamingException {
        unbind(name.toString());
    }

    /**
     * Rename the object specified by oldname to newname
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    @Override
    public void rename(Name oldname, Name newname) throws NamingException {
        rename(oldname.toString(), newname.toString());
    }

    /**
     * Rename the object specified by oldname to newname
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    @Override
    public void rename(String oldname, String newname)
            throws NamingException {
        if (oldname.equals("") || newname.equals("")) {
            throw new InvalidNameException("Cannot rename empty name");
        }

        lock.writeLock().lock() ;
        try {
            // Check if new name exists
            if (bindings.get(newname) != null) {
                throw new NameAlreadyBoundException(newname +
                        " is already bound");
            }

            // Check if old name is bound
            Object oldBinding = bindings.remove(oldname);
            if (oldBinding == null) {
                throw new NameNotFoundException(oldname + " not bound");
            }

            bindings.put(newname, oldBinding);
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * list the objects stored by the current context
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    public Hashtable list() {
        lock.readLock().lock();
        try {
            return new Hashtable(bindings);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * List the objects specified by name.
     *
     * @throws NamingException          if there is a naming exception
     * @throws java.rmi.RemoteException if there is a RMI exception
     */
    public Hashtable listContext(String name) throws NamingException {
        lock.readLock().lock();
        try {
            if (logger.isLoggable(Level.FINE)) {
                print(bindings);
            }
            if (name.equals("")) {
                return new Hashtable(bindings);
            }

            Object target = lookup(name);
            if (target instanceof TransientContext) {
                return ((TransientContext) target).listContext("");
            }
            throw new NotContextException(name + " cannot be listed");
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * List the objects specified by name.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public NamingEnumeration list(Name name) throws NamingException {
        return list(name.toString());
    }

    /**
     * List the objects specified by name.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public NamingEnumeration list(String name) throws NamingException {
        lock.readLock().lock() ;
        try {
            if (logger.isLoggable(Level.FINE)) {
                print(bindings);
            }
            if (name.equals("")) {
                return new RepNames(new Hashtable(bindings));
            }

            Object target = lookup(name);
            if (target instanceof Context) {
                return ((Context) target).list("");
            }
            throw new NotContextException(name + " cannot be listed");
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * List the bindings of objects present in name.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public NamingEnumeration listBindings(String name) throws NamingException {
        lock.readLock().lock() ;
        try {
            if (name.equals("")) {
                return new RepBindings(new Hashtable(bindings));
            }

            Object target = lookup(name);
            if (target instanceof Context) {
                return ((Context) target).listBindings("");
            }
            throw new NotContextException(name + " cannot be listed");
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * List the binding of objects specified by name.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public NamingEnumeration listBindings(Name name) throws NamingException {
        return listBindings(name.toString());
    }

    /**
     * Lookup the name.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public Object lookupLink(String name) throws NamingException {
        // This flat context does not treat links specially
        return lookup(name);
    }

    /**
     * Lookup name.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public Object lookupLink(Name name) throws NamingException {
        // Flat namespace; no federation; just call string version
        return lookupLink(name.toString());
    }

    /**
     * List the NameParser specified by name.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public NameParser getNameParser(String name) throws NamingException {
        return myParser;
    }

    /**
     * List the NameParser specified by name.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public NameParser getNameParser(Name name) throws NamingException {
        // Flat namespace; no federation; just call string version
        return getNameParser(name.toString());
    }

    /**
     * Compose a new name specified by name and prefix.
     *
     * @return null
     * @throws NamingException if there is a naming exception
     */
    @Override
    public String composeName(String name, String prefix)
            throws NamingException {
        return null;
    }

    /**
     * Compose a new name specified by name and prefix.
     *
     * @return Name result of the concatenation
     * @throws NamingException if there is a naming exception
     */
    @Override
    public Name composeName(Name name, Name prefix)
            throws NamingException {
        Name result = (Name) (prefix.clone());
        result.addAll(name);
        return result;
    }

    /**
     * Add the property name and value to the environment.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public Object addToEnvironment(String propName, Object propVal)
            throws NamingException {
        lock.writeLock().lock() ;
        try {
            if (myEnv == null) {
                myEnv = new Hashtable(5, 0.75f);
            }
            return myEnv.put(propName, propVal);
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Remove property from the environment.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public Object removeFromEnvironment(String propName)
            throws NamingException {
        lock.writeLock().lock() ;
        try {
            if (myEnv == null) {
                return null;
            }
            return myEnv.remove(propName);
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * List the current environment.
     *
     * @throws NamingException if there is a naming exception
     */
    @Override
    public Hashtable getEnvironment() throws NamingException {
        lock.writeLock().lock() ;
        try {
            if (myEnv == null) {
                // Must return non-null
                myEnv = new Hashtable(3, 0.75f);
            }
            return myEnv;
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Invalidate the current environment.
     */
    @Override
    public void close() throws NamingException {
        myEnv = null;
    }

    /**
     * Operation not supported.
     */
    @Override
    public String getNameInNamespace() throws NamingException {
        throw new OperationNotSupportedException("getNameInNamespace() " +
                "not implemented");
    }

    /**
     * Print the current hashtable.  Should only be invoked for FINE Level logging.
     */
    private static void print(Map ht) {
        for (Map.Entry entry : ht.entrySet()) {
            Object value = entry.getValue();
            logger.log(Level.FINE, "[{0}, {1}:{2}]",
                    new Object[]{entry.getKey(), value, value.getClass().getName()});
            // END OF IASRI 4660742
        }
    }

    // Class for enumerating name/class pairs
    static class RepNames implements NamingEnumeration {
        private Map nameToClassName =
            new HashMap() ;
        private Iterator iter ;

        RepNames(Hashtable bindings) {
            Set names = new HashSet() ;
            for (Object str : bindings.keySet()) {
                names.add( (String)str ) ;
            }

            iter = names.iterator() ;

            for (Object obj : bindings.entrySet() ) {
                Map.Entry entry = (Map.Entry)obj ;
                nameToClassName.put( (String)entry.getKey(),
                    entry.getValue().getClass().getName()) ;
            }
        }

        @Override
        public boolean hasMoreElements() {
            return iter.hasNext();
        }

        @Override
        public boolean hasMore() throws NamingException {
            return hasMoreElements();
        }

        @Override
        public T nextElement() {
            if (iter.hasNext()) {
                String name = iter.next();
                String className = nameToClassName.get(name) ;
                return (T) (new NameClassPair(name, className));
            } else {
                return null;
            }
        }

        @Override
        public T next() throws NamingException {
            return nextElement();
        }

        @Override
        public void close() {
            //no-op since no steps needed to free up resources
        }
    }

    // Class for enumerating bmesindings
    static class RepBindings implements NamingEnumeration {
        Enumeration names;
        Hashtable bindings;

        RepBindings(Hashtable bindings) {
            this.bindings = bindings;
            this.names = bindings.keys();
        }

        @Override
        public boolean hasMoreElements() {
            return names.hasMoreElements();
        }

        @Override
        public boolean hasMore() throws NamingException {
            return hasMoreElements();
        }

        @Override
        public T nextElement() {
            if (hasMoreElements()) {
                String name = (String) names.nextElement();
                return (T) (new Binding(name, bindings.get(name)));
            } else {
                return null;
            }
        }

        @Override
        public T next() throws NamingException {
            return nextElement();
        }

        @Override
        public void close() {
            //no-op since no steps needed to free up resources
        }
    }
}














© 2015 - 2024 Weber Informatics LLC | Privacy Policy