/*
 * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

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<String,Object> bindings = new HashMap<String,Object>();
    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<NameClassPair> 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<NameClassPair> list(String name) throws NamingException {
        lock.readLock().lock() ;
        try {
            if (logger.isLoggable(Level.FINE)) {
                print(bindings);
            }
            if (name.equals("")) {
                return new RepNames<NameClassPair>(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<Binding> listBindings(String name) throws NamingException {
        lock.readLock().lock() ;
        try {
            if (name.equals("")) {
                return new RepBindings<Binding>(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<Binding> 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<String,Object> ht) {
        for (Map.Entry<String, Object> 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<T> implements NamingEnumeration<T> {
        private Map<String,String> nameToClassName =
            new HashMap<String,String>() ;
        private Iterator<String> iter ;

        RepNames(Hashtable bindings) {
            Set<String> names = new HashSet<String>() ;
            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<T> implements NamingEnumeration<T> {
        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
        }
    }
}










