/*
 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.rmi.registry;


import java.util.Hashtable;
import java.util.Properties;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;

import javax.naming.*;
import javax.naming.spi.NamingManager;


/**
 * A RegistryContext is a context representing a remote RMI registry.
 *
 * @author Scott Seligman
 */


public class RegistryContext implements Context, Referenceable {

    private Hashtable<String, Object> environment;
    private Registry registry;
    private String host;
    private int port;
    private static final NameParser nameParser = new AtomicNameParser();
    private static final String SOCKET_FACTORY = "com.sun.jndi.rmi.factory.socket";

    Reference reference = null; // ref used to create this context, if any

    // Environment property that, if set, indicates that a security
    // manager should be installed (if none is already in place).
    public static final String SECURITY_MGR =
            "java.naming.rmi.security.manager";

    /**
     * Returns a context for the registry at a given host and port.
     * If "host" is null, uses default host.
     * If "port" is non-positive, uses default port.
     * Cloning of "env" is handled by caller; see comments within
     * RegistryContextFactory.getObjectInstance(), for example.
     */
    @SuppressWarnings("unchecked")
    public RegistryContext(String host, int port, Hashtable<?, ?> env)
            throws NamingException
    {
        environment = (env == null)
                      ? new Hashtable<String, Object>(5)
                      : (Hashtable<String, Object>) env;
        if (environment.get(SECURITY_MGR) != null) {
            installSecurityMgr();
        }

        // chop off '[' and ']' in an IPv6 literal address
        if ((host != null) && (host.charAt(0) == '[')) {
            host = host.substring(1, host.length() - 1);
        }

        RMIClientSocketFactory socketFactory =
                (RMIClientSocketFactory) environment.get(SOCKET_FACTORY);
        registry = getRegistry(host, port, socketFactory);
        this.host = host;
        this.port = port;
    }

    /**
     * Returns a clone of a registry context.  The context's private state
     * is independent of the original's (so closing one context, for example,
     * won't close the other).
     */
    // %%% Alternatively, this could be done with a clone() method.
    @SuppressWarnings("unchecked") // clone()
    RegistryContext(RegistryContext ctx) {
        environment = (Hashtable<String, Object>)ctx.environment.clone();
        registry = ctx.registry;
        host = ctx.host;
        port = ctx.port;
        reference = ctx.reference;
    }

    protected void finalize() {
        close();
    }

    public Object lookup(Name name) throws NamingException {
        if (name.isEmpty()) {
            return (new RegistryContext(this));
        }
        Remote obj;
        try {
            obj = registry.lookup(name.get(0));
        } catch (NotBoundException e) {
            throw (new NameNotFoundException(name.get(0)));
        } catch (RemoteException e) {
            throw (NamingException)wrapRemoteException(e).fillInStackTrace();
        }
        return (decodeObject(obj, name.getPrefix(1)));
    }

    public Object lookup(String name) throws NamingException {
        return lookup(new CompositeName(name));
    }

    /**
     * If the object to be bound is both Remote and Referenceable, binds the
     * object itself, not its Reference.
     */
    public void bind(Name name, Object obj) throws NamingException {
        if (name.isEmpty()) {
            throw (new InvalidNameException(
                    "RegistryContext: Cannot bind empty name"));
        }
        try {
            registry.bind(name.get(0), encodeObject(obj, name.getPrefix(1)));
        } catch (AlreadyBoundException e) {
            NamingException ne = new NameAlreadyBoundException(name.get(0));
            ne.setRootCause(e);
            throw ne;
        } catch (RemoteException e) {
            throw (NamingException)wrapRemoteException(e).fillInStackTrace();
        }
    }

    public void bind(String name, Object obj) throws NamingException {
        bind(new CompositeName(name), obj);
    }

    public void rebind(Name name, Object obj) throws NamingException {
        if (name.isEmpty()) {
            throw (new InvalidNameException(
                    "RegistryContext: Cannot rebind empty name"));
        }
        try {
            registry.rebind(name.get(0), encodeObject(obj, name.getPrefix(1)));
        } catch (RemoteException e) {
            throw (NamingException)wrapRemoteException(e).fillInStackTrace();
        }
    }

    public void rebind(String name, Object obj) throws NamingException {
        rebind(new CompositeName(name), obj);
    }

    public void unbind(Name name) throws NamingException {
        if (name.isEmpty()) {
            throw (new InvalidNameException(
                    "RegistryContext: Cannot unbind empty name"));
        }
        try {
            registry.unbind(name.get(0));
        } catch (NotBoundException e) {
            // method is idempotent
        } catch (RemoteException e) {
            throw (NamingException)wrapRemoteException(e).fillInStackTrace();
        }
    }

    public void unbind(String name) throws NamingException {
        unbind(new CompositeName(name));
    }

    /**
     * Rename is implemented by this sequence of operations:
     * lookup, bind, unbind.  The sequence is not performed atomically.
     */
    public void rename(Name oldName, Name newName) throws NamingException {
        bind(newName, lookup(oldName));
        unbind(oldName);
    }

    public void rename(String name, String newName) throws NamingException {
        rename(new CompositeName(name), new CompositeName(newName));
    }

    public NamingEnumeration<NameClassPair> list(Name name) throws
            NamingException {
        if (!name.isEmpty()) {
            throw (new InvalidNameException(
                    "RegistryContext: can only list \"\""));
        }
        try {
            String[] names = registry.list();
            return (new NameClassPairEnumeration(names));
        } catch (RemoteException e) {
            throw (NamingException)wrapRemoteException(e).fillInStackTrace();
        }
    }

    public NamingEnumeration<NameClassPair> list(String name) throws
            NamingException {
        return list(new CompositeName(name));
    }

    public NamingEnumeration<Binding> listBindings(Name name)
            throws NamingException
    {
        if (!name.isEmpty()) {
            throw (new InvalidNameException(
                    "RegistryContext: can only list \"\""));
        }
        try {
            String[] names = registry.list();
            return (new BindingEnumeration(this, names));
        } catch (RemoteException e) {
            throw (NamingException)wrapRemoteException(e).fillInStackTrace();
        }
    }

    public NamingEnumeration<Binding> listBindings(String name) throws
            NamingException {
        return listBindings(new CompositeName(name));
    }

    public void destroySubcontext(Name name) throws NamingException {
        throw (new OperationNotSupportedException());
    }

    public void destroySubcontext(String name) throws NamingException {
        throw (new OperationNotSupportedException());
    }

    public Context createSubcontext(Name name) throws NamingException {
        throw (new OperationNotSupportedException());
    }

    public Context createSubcontext(String name) throws NamingException {
        throw (new OperationNotSupportedException());
    }

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

    public Object lookupLink(String name) throws NamingException {
        return lookup(name);
    }

    public NameParser getNameParser(Name name) throws NamingException {
        return nameParser;
    }

    public NameParser getNameParser(String name) throws NamingException {
        return nameParser;
    }

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

    public String composeName(String name, String prefix)
            throws NamingException
    {
        return composeName(new CompositeName(name),
                           new CompositeName(prefix)).toString();
    }

    public Object removeFromEnvironment(String propName)
            throws NamingException
    {
        return environment.remove(propName);
    }

    public Object addToEnvironment(String propName, Object propVal)
            throws NamingException
    {
        if (propName.equals(SECURITY_MGR)) {
            installSecurityMgr();
        }
        return environment.put(propName, propVal);
    }

    @SuppressWarnings("unchecked") // clone()
    public Hashtable<String, Object> getEnvironment() throws NamingException {
        return (Hashtable<String, Object>)environment.clone();
    }

    public void close() {
        environment = null;
        registry = null;
        // &&& If we were caching registry connections, we would probably
        // uncache this one now.
    }

    public String getNameInNamespace() {
        return ""; // Registry has an empty name
    }

    /**
     * Returns an RMI registry reference for this context.
     *<p>
     * If this context was created from a reference, that reference is
     * returned.  Otherwise, an exception is thrown if the registry's
     * host is "localhost" or the default (null).  Although this could
     * possibly make for a valid reference, it's far more likely to be
     * an easily made error.
     *
     * @see RegistryContextFactory
     */
    public Reference getReference() throws NamingException {
        if (reference != null) {
            return (Reference)reference.clone();  // %%% clone the addrs too?
        }
        if (host == null || host.equals("localhost")) {
            throw (new ConfigurationException(
                    "Cannot create a reference for an RMI registry whose " +
                    "host was unspecified or specified as \"localhost\""));
        }
        String url = "rmi://";

        // Enclose IPv6 literal address in '[' and ']'
        url = (host.indexOf(":") > -1) ? url + "[" + host + "]" :
                                         url + host;
        if (port > 0) {
            url += ":" + Integer.toString(port);
        }
        RefAddr addr = new StringRefAddr(RegistryContextFactory.ADDRESS_TYPE,
                                         url);
        return (new Reference(RegistryContext.class.getName(),
                              addr,
                              RegistryContextFactory.class.getName(),
                              null));
    }


    /**
     * Wrap a RemoteException inside a NamingException.
     */
    public static NamingException wrapRemoteException(RemoteException re) {

        NamingException ne;

        if (re instanceof ConnectException) {
            ne = new ServiceUnavailableException();

        } else if (re instanceof AccessException) {
            ne = new NoPermissionException();

        } else if (re instanceof StubNotFoundException ||
                   re instanceof UnknownHostException ||
                   re instanceof SocketSecurityException) {
            ne = new ConfigurationException();

        } else if (re instanceof ExportException ||
                   re instanceof ConnectIOException ||
                   re instanceof MarshalException ||
                   re instanceof UnmarshalException ||
                   re instanceof NoSuchObjectException) {
            ne = new CommunicationException();

        } else if (re instanceof ServerException &&
                   re.detail instanceof RemoteException) {
            ne = wrapRemoteException((RemoteException)re.detail);

        } else {
            ne = new NamingException();
        }
        ne.setRootCause(re);
        return ne;
    }

    /**
     * Returns the registry at a given host, port and socket factory.
     * If "host" is null, uses default host.
     * If "port" is non-positive, uses default port.
     * If "socketFactory" is null, uses the default socket.
     */
    private static Registry getRegistry(String host, int port,
                RMIClientSocketFactory socketFactory)
            throws NamingException
    {
        // %%% We could cache registry connections here.  The transport layer
        // may already reuse connections.
        try {
            if (socketFactory == null) {
                return LocateRegistry.getRegistry(host, port);
            } else {
                return LocateRegistry.getRegistry(host, port, socketFactory);
            }
        } catch (RemoteException e) {
            throw (NamingException)wrapRemoteException(e).fillInStackTrace();
        }
    }

    /**
     * Attempts to install a security manager if none is currently in
     * place.
     */
    private static void installSecurityMgr() {

        try {
            System.setSecurityManager(new RMISecurityManager());
        } catch (Exception e) {
        }
    }

    /**
     * Encodes an object prior to binding it in the registry.  First,
     * NamingManager.getStateToBind() is invoked.  If the resulting
     * object is Remote, it is returned.  If it is a Reference or
     * Referenceable, the reference is wrapped in a Remote object.
     * Otherwise, an exception is thrown.
     *
     * @param name      The object's name relative to this context.
     */
    private Remote encodeObject(Object obj, Name name)
            throws NamingException, RemoteException
    {
        obj = NamingManager.getStateToBind(obj, name, this, environment);

        if (obj instanceof Remote) {
            return (Remote)obj;
        }
        if (obj instanceof Reference) {
            return (new ReferenceWrapper((Reference)obj));
        }
        if (obj instanceof Referenceable) {
            return (new ReferenceWrapper(((Referenceable)obj).getReference()));
        }
        throw (new IllegalArgumentException(
                "RegistryContext: " +
                "object to bind must be Remote, Reference, or Referenceable"));
    }

    /**
     * Decodes an object that has been retrieved from the registry.
     * First, if the object is a RemoteReference, the Reference is
     * unwrapped.  Then, NamingManager.getObjectInstance() is invoked.
     *
     * @param name      The object's name relative to this context.
     */
    private Object decodeObject(Remote r, Name name) throws NamingException {
        try {
            Object obj = (r instanceof RemoteReference)
                        ? ((RemoteReference)r).getReference()
                        : (Object)r;
            return NamingManager.getObjectInstance(obj, name, this,
                                                   environment);
        } catch (NamingException e) {
            throw e;
        } catch (RemoteException e) {
            throw (NamingException)
                wrapRemoteException(e).fillInStackTrace();
        } catch (Exception e) {
            NamingException ne = new NamingException();
            ne.setRootCause(e);
            throw ne;
        }
    }

}


/**
 * A name parser for case-sensitive atomic names.
 */
class AtomicNameParser implements NameParser {
    private static final Properties syntax = new Properties();

    public Name parse(String name) throws NamingException {
        return (new CompoundName(name, syntax));
    }
}


/**
 * An enumeration of name / class-name pairs.
 */
class NameClassPairEnumeration implements NamingEnumeration<NameClassPair> {
    private final String[] names;
    private int nextName;       // index into "names"

    NameClassPairEnumeration(String[] names) {
        this.names = names;
        nextName = 0;
    }

    public boolean hasMore() {
        return (nextName < names.length);
    }

    public NameClassPair next() throws NamingException {
        if (!hasMore()) {
            throw (new java.util.NoSuchElementException());
        }
        // Convert name to a one-element composite name, so embedded
        // meta-characters are properly escaped.
        String name = names[nextName++];
        Name cname = (new CompositeName()).add(name);
        NameClassPair ncp = new NameClassPair(cname.toString(),
                                            "java.lang.Object");
        ncp.setNameInNamespace(name);
        return ncp;
    }

    public boolean hasMoreElements() {
        return hasMore();
    }

    public NameClassPair nextElement() {
        try {
            return next();
        } catch (NamingException e) {   // should never happen
            throw (new java.util.NoSuchElementException(
                    "javax.naming.NamingException was thrown"));
        }
    }

    public void close() {
        nextName = names.length;
    }
}


/**
 * An enumeration of Bindings.
 *
 * The actual registry lookups are performed when next() is called.  It would
 * be nicer to defer this until the object (or its class name) is actually
 * requested.  The problem with that approach is that Binding.getObject()
 * cannot throw NamingException.
 */
class BindingEnumeration implements NamingEnumeration<Binding> {
    private RegistryContext ctx;
    private final String[] names;
    private int nextName;       // index into "names"

    BindingEnumeration(RegistryContext ctx, String[] names) {
        // Clone ctx in case someone closes it before we're through.
        this.ctx = new RegistryContext(ctx);
        this.names = names;
        nextName = 0;
    }

    protected void finalize() {
        ctx.close();
    }

    public boolean hasMore() {
        if (nextName >= names.length) {
            ctx.close();
        }
        return (nextName < names.length);
    }

    public Binding next() throws NamingException {
        if (!hasMore()) {
            throw (new java.util.NoSuchElementException());
        }
        // Convert name to a one-element composite name, so embedded
        // meta-characters are properly escaped.
        String name = names[nextName++];
        Name cname = (new CompositeName()).add(name);

        Object obj = ctx.lookup(cname);
        String cnameStr = cname.toString();
        Binding binding = new Binding(cnameStr, obj);
        binding.setNameInNamespace(cnameStr);
        return binding;
    }

    public boolean hasMoreElements() {
        return hasMore();
    }

    public Binding nextElement() {
        try {
            return next();
        } catch (NamingException e) {
            throw (new java.util.NoSuchElementException(
                    "javax.naming.NamingException was thrown"));
        }
    }

    public void close () {
        finalize();
    }
}
