Package org.apache.harmony.jndi.provider.rmi.registry

Source Code of org.apache.harmony.jndi.provider.rmi.registry.RegistryContext

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/

/**
* @author  Vasily Zakharov
*/

package org.apache.harmony.jndi.provider.rmi.registry;

import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.ConnectException;
import java.rmi.ConnectIOException;
import java.rmi.MarshalException;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
import java.rmi.RMISecurityManager;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.rmi.StubNotFoundException;
import java.rmi.UnknownHostException;
import java.rmi.UnmarshalException;
import java.rmi.activation.ActivateFailedException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.ExportException;
import java.rmi.server.RMIClientSocketFactory;
import java.util.Hashtable;

import javax.naming.Binding;
import javax.naming.CommunicationException;
import javax.naming.CompositeName;
import javax.naming.ConfigurationException;
import javax.naming.Context;
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.NoPermissionException;
import javax.naming.NotContextException;
import javax.naming.OperationNotSupportedException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.ServiceUnavailableException;
import javax.naming.StringRefAddr;
import javax.naming.spi.NamingManager;

import org.apache.harmony.jndi.internal.nls.Messages;

/**
* RMI Registry context implementation.
*/
public class RegistryContext implements Context, Referenceable {

    /**
     * System property used to state whether the RMI security manager should be
     * installed.
     */
    public static final String SECURITY_MANAGER = "java.naming.rmi.security.manager"; //$NON-NLS-1$

    /**
     * System property used to supply the name of the
     * {@link RMIClientSocketFactory} to use.
     */
    public static final String CLIENT_SOCKET_FACTORY = "org.apache.harmony.jndi.provider.rmi.registry.clientSocketFactory"; //$NON-NLS-1$

    /**
     * Prefix for RMI URLs.
     */
    public static final String RMI_URL_PREFIX = "rmi:"; //$NON-NLS-1$

    /**
     * Address type for RMI context references.
     */
    public static final String ADDRESS_TYPE = "URL"; //$NON-NLS-1$

    /**
     * Name parser.
     */
    protected static final NameParser nameParser = new AtomicNameParser();

    /**
     * Registry host, stored to produce copies of this context.
     */
    protected String host;

    /**
     * Registry port, stored to produce copies of this context.
     */
    protected int port;

    /**
     * RMI client socket factory, stored to produce copies of this context.
     */
    protected RMIClientSocketFactory csf;

    /**
     * Local environment.
     */
    protected Hashtable<Object, Object> environment;

    /**
     * RMI Registry.
     */
    protected Registry registry;

    /**
     * Reference for this context, initialized by
     * {@link RegistryContextFactory#getObjectInstance(Object, Name, Context, Hashtable)}.
     */
    protected Reference reference;

    /**
     * Creates RMI registry context bound to RMI Registry operating on the
     * specified host and port.
     *
     * @param host
     *            Host. If <code>null</code>, localhost is assumed.
     *
     * @param port
     *            Port. If <code>0</code>, default registry port (<code>1099</code>)
     *            is assumed.
     *
     * @param environment
     *            Context environment, may be <code>null</code> which denotes
     *            empty environment.
     *
     * @throws NamingException
     *             If some naming error occurs.
     */
    @SuppressWarnings("unchecked")
    public RegistryContext(String host, int port, Hashtable<?, ?> environment)
            throws NamingException {
        this.host = host;
        this.port = port;

        this.environment = ((environment != null) ? (Hashtable<Object, Object>) environment
                .clone()
                : new Hashtable<Object, Object>());

        if (this.environment.get(SECURITY_MANAGER) != null) {
            installSecurityManager();
        }

        String clientSocketFactoryName = (String) this.environment
                .get(CLIENT_SOCKET_FACTORY);

        if (clientSocketFactoryName == null) {
            csf = null;
        } else {
            try {
                csf = (RMIClientSocketFactory) Class.forName(
                        clientSocketFactoryName, true,
                        Thread.currentThread().getContextClassLoader())
                        .newInstance();
            } catch (ClassNotFoundException e) {
                // jndi.79=RMI Client Socket Factory cannot be instantiated
                throw (ConfigurationException) new ConfigurationException(
                        Messages.getString("jndi.79")) //$NON-NLS-1$
                        .initCause(e);
            } catch (InstantiationException e) {
                // jndi.79=RMI Client Socket Factory cannot be instantiated
                throw (ConfigurationException) new ConfigurationException(
                        Messages.getString("jndi.79")) //$NON-NLS-1$
                        .initCause(e);
            } catch (IllegalAccessException e) {
                // jndi.79=RMI Client Socket Factory cannot be instantiated
                throw (NoPermissionException) new NoPermissionException(
                        Messages.getString("jndi.79")) //$NON-NLS-1$
                        .initCause(e);
            }
        }
        registry = getRegistry(host, port, csf);
        reference = null;
    }

    /**
     * Creates RMI registry context by copying the specified context.
     *
     * @param context
     *            Context to copy.
     */
    @SuppressWarnings("unchecked")
    protected RegistryContext(RegistryContext context) {
        host = context.host;
        port = context.port;
        csf = context.csf;
        environment = (Hashtable<Object, Object>) context.environment.clone();
        registry = context.registry;
        reference = context.reference;
    }

    /**
     * {@inheritDoc}
     */
    public Object lookup(Name name) throws NamingException {
        if (name.isEmpty()) {
            return cloneContext();
        }
        String stringName = getMyComponents(name);

        try {
            return getObjectInstance(stringName, registry.lookup(stringName));
        } catch (NotBoundException e) {
            // jndi.7A=Name is not bound: {0}
            throw (NameNotFoundException) new NameNotFoundException(Messages
                    .getString("jndi.7A", stringName)).initCause(e); //$NON-NLS-1$
        } catch (RemoteException e) {
            throw (NamingException) newNamingException(e).fillInStackTrace();
        }
    }

    /**
     * {@inheritDoc}
     */
    public Object lookup(String name) throws NamingException {
        return lookup(new CompositeName(name));
    }

    /**
     * {@inheritDoc}
     */
    public Object lookupLink(Name name) throws NamingException {
        return lookup(name);
    }

    /**
     * {@inheritDoc}
     */
    public Object lookupLink(String name) throws NamingException {
        return lookupLink(new CompositeName(name));
    }

    /**
     * {@inheritDoc}
     */
    public void bind(Name name, Object obj) throws NamingException {
        if (name.isEmpty()) {
            // jndi.7B=Cannot bind empty name
            throw new InvalidNameException(Messages.getString("jndi.7B")); //$NON-NLS-1$
        }
        String stringName = getMyComponents(name);

        try {
            registry.bind(stringName, getStateToBind(stringName, obj));
        } catch (AlreadyBoundException e) {
            // jndi.7C=Name is already bound: {0}
            throw (NameAlreadyBoundException) new NameAlreadyBoundException(
                    Messages.getString("jndi.7C", stringName)).initCause(e); //$NON-NLS-1$
        } catch (RemoteException e) {
            throw (NamingException) newNamingException(e).fillInStackTrace();
        }
    }

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

    /**
     * {@inheritDoc}
     */
    public void rebind(Name name, Object obj) throws NamingException {
        if (name.isEmpty()) {
            // jndi.7D=Cannot rebind empty name
            throw new InvalidNameException(Messages.getString("jndi.7D")); //$NON-NLS-1$
        }
        String stringName = getMyComponents(name);

        try {
            registry.rebind(stringName, getStateToBind(stringName, obj));
        } catch (RemoteException e) {
            throw (NamingException) newNamingException(e).fillInStackTrace();
        }
    }

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

    /**
     * {@inheritDoc}
     */
    public void unbind(Name name) throws NamingException {
        if (name.isEmpty()) {
            // jndi.7E=Cannot unbind empty name
            throw new InvalidNameException(Messages.getString("jndi.7E")); //$NON-NLS-1$
        }
        String stringName = getMyComponents(name);

        try {
            registry.unbind(stringName);
        } catch (NotBoundException e) {
            // Returning ok if target name is not found, by the specification.
        } catch (RemoteException e) {
            throw (NamingException) newNamingException(e).fillInStackTrace();
        }
    }

    /**
     * {@inheritDoc}
     */
    public void unbind(String name) throws NamingException {
        unbind(new CompositeName(name));
    }

    /**
     * {@inheritDoc}
     */
    public Context createSubcontext(Name name)
            throws OperationNotSupportedException {
        // jndi.7F=RMI Registry is a flat context and doesn't support
        // subcontexts
        throw new OperationNotSupportedException(Messages.getString("jndi.7F")); //$NON-NLS-1$
    }

    /**
     * {@inheritDoc}
     */
    public Context createSubcontext(String name) throws NamingException {
        return createSubcontext(new CompositeName(name));
    }

    /**
     * {@inheritDoc}
     */
    public void destroySubcontext(Name name)
            throws OperationNotSupportedException {
        // jndi.7F=RMI Registry is a flat context and doesn't support
        // subcontexts
        throw new OperationNotSupportedException(Messages.getString("jndi.7F")); //$NON-NLS-1$
    }

    /**
     * {@inheritDoc}
     */
    public void destroySubcontext(String name) throws NamingException {
        destroySubcontext(new CompositeName(name));
    }

    /**
     * {@inheritDoc}
     */
    public void rename(Name oldName, Name newName) throws NamingException {
        bind(newName, lookup(oldName));
        unbind(oldName);
    }

    /**
     * {@inheritDoc}
     */
    public void rename(String oldName, String newName) throws NamingException {
        rename(new CompositeName(oldName), new CompositeName(newName));
    }

    /**
     * {@inheritDoc}
     */
    public NamingEnumeration<NameClassPair> list(Name name)
            throws NamingException {
        if (name.isEmpty()) {
            try {
                return new NameClassPairEnumeration(registry.list());
            } catch (RemoteException e) {
                throw (NamingException) newNamingException(e)
                        .fillInStackTrace();
            }
        }
        Object obj = lookup(name);

        if (obj instanceof Context) {
            try {
                return ((Context) obj).list(""); //$NON-NLS-1$
            } finally {
                ((Context) obj).close();
            }
        }
        // jndi.80=Name specifies an object that is not a context: {0}
        throw new NotContextException(Messages.getString("jndi.80", name)); //$NON-NLS-1$
    }

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

    /**
     * {@inheritDoc}
     */
    public NamingEnumeration<Binding> listBindings(Name name)
            throws NamingException {
        if (name.isEmpty()) {
            try {
                return new BindingEnumeration(registry.list(), this);
            } catch (RemoteException e) {
                throw (NamingException) newNamingException(e)
                        .fillInStackTrace();
            }
        }
        Object obj = lookup(name);

        if (obj instanceof Context) {
            try {
                return ((Context) obj).listBindings(""); //$NON-NLS-1$
            } finally {
                ((Context) obj).close();
            }
        }
        // jndi.80=Name specifies an object that is not a context: {0}
        throw new NotContextException(Messages.getString("jndi.80", name)); //$NON-NLS-1$
    }

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

    /**
     * {@inheritDoc}
     */
    public NameParser getNameParser(Name name) {
        return nameParser;
    }

    /**
     * {@inheritDoc}
     */
    public NameParser getNameParser(String name) throws NamingException {
        return getNameParser(new CompositeName(name));
    }

    /**
     * {@inheritDoc}
     */
    public Name composeName(Name name, Name prefix) throws NamingException {
        return ((Name) prefix.clone()).addAll(name);
    }

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

    /**
     * {@inheritDoc}
     */
    public String getNameInNamespace() {
        return ""; //$NON-NLS-1$
    }

    /**
     * {@inheritDoc}
     */
    public Hashtable<?, ?> getEnvironment() {
        return (Hashtable<?, ?>) environment.clone();
    }

    /**
     * {@inheritDoc}
     */
    public Object addToEnvironment(String propName, Object propVal)
            throws NoPermissionException {
        if (propName.equals(SECURITY_MANAGER)) {
            installSecurityManager();
        }
        return environment.put(propName, propVal);
    }

    /**
     * {@inheritDoc}
     */
    public Object removeFromEnvironment(String propName) {
        return environment.remove(propName);
    }

    /**
     * {@inheritDoc}
     */
    public void close() {
        environment = null;
        registry = null;
    }

    /**
     * {@inheritDoc}
     */
    public Reference getReference() throws NamingException {
        if (reference == null) {
            if ((host == null) || (host.equals("localhost"))) { //$NON-NLS-1$
                // jndi.81=Cannot create reference for RMI registry that is
                // being accessed using localhost
                throw new ConfigurationException(Messages.getString("jndi.81")); //$NON-NLS-1$
            }
            reference = new Reference(RegistryContext.class.getName(),
                    new StringRefAddr(ADDRESS_TYPE, RMI_URL_PREFIX + "//" //$NON-NLS-1$
                            + host + ((port > 0) ? (":" + port) : "")), //$NON-NLS-1$ //$NON-NLS-2$
                    RegistryContextFactory.class.getName(), null);
        }
        return (Reference) reference.clone();
    }

    /**
     * Initializes reference for this context instance. Called by
     * {@link RegistryContextFactory#getObjectInstance(Object, Name, Context, Hashtable)}.
     *
     * @param reference
     *            Reference for this context instance.
     */
    protected void setReference(Reference reference) {
        this.reference = reference;
    }

    /**
     * Returns a clone of this context.
     *
     * @return Clone of this context.
     */
    protected RegistryContext cloneContext() {
        return new RegistryContext(this);
    }

    /**
     * Verifies that the specified name is valid for this context and returns
     * string representation of that name for this provider.
     *
     * Returns returns first component of a {@link CompositeName} or a string
     * representation of a name otherwise.
     *
     * @param name
     *            Name to verify.
     *
     * @return {@link CompositeName#get(int) CompositeName#get(0)} if
     *         <code>name</code> is a {@link CompositeName},
     *         {@link Object#toString() name.toString()} otherwise.
     */
    protected String getMyComponents(Name name) {
        if (name instanceof CompositeName) {
            return name.get(0);
        }
        return name.toString();
    }

    /**
     * Prepares object for binding. It calls
     * {@link NamingManager#getStateToBind(Object, Name, Context, Hashtable)}
     * and makes the resulting object {@link Remote} by wrapping it into
     * {@link RemoteReferenceWrapper}.
     *
     * @param name
     *            Object name.
     *
     * @param obj
     *            Object to prepare for binding.
     *
     * @return Object ready for binding.
     *
     * @throws NamingException
     *             If some naming error occurs.
     *
     * @throws RemoteException
     *             If remote exception occurs.
     */
    protected Remote getStateToBind(String name, Object obj)
            throws NamingException, RemoteException {
        obj = NamingManager.getStateToBind(obj, new CompositeName().add(name),
                this, environment);

        if (obj instanceof Remote) {
            return (Remote) obj;
        }

        if (obj instanceof Reference) {
            return new RemoteReferenceWrapper((Reference) obj);
        }

        if (obj instanceof Referenceable) {
            return new RemoteReferenceWrapper(((Referenceable) obj)
                    .getReference());
        }
        // jndi.82=Cannot bind to RMI Registry object that is neither Remote nor
        // Reference nor Referenceable
        throw new IllegalArgumentException(Messages.getString("jndi.82")); //$NON-NLS-1$
    }

    /**
     * Processes object returned from {@linkplain Registry RMI registry}. It
     * unwraps {@link RemoteReference} if necessary and calls
     * {@link NamingManager#getObjectInstance(Object, Name, Context, Hashtable)}.
     *
     * @param name
     *            Object name.
     *
     * @param remote
     *            Returned object.
     *
     * @return Processed object.
     *
     * @throws NamingException
     *             If some naming error occurs.
     *
     * @throws RemoteException
     *             If remote exception occurs.
     */
    protected Object getObjectInstance(String name, Remote remote)
            throws NamingException, RemoteException {
        Object obj;

        obj = ((remote instanceof RemoteReference) ? ((RemoteReference) remote)
                .getReference() : (Object) remote);

        try {
            return NamingManager.getObjectInstance(obj, new CompositeName()
                    .add(name), this, environment);
        } catch (NamingException e) {
            throw e;
        } catch (RemoteException e) {
            throw e;
        } catch (Exception e) {
            // jndi.83=NamingManager.getObjectInstance() failed
            throw (NamingException) new NamingException(Messages
                    .getString("jndi.83")).initCause(e); //$NON-NLS-1$
        }
    }

    /**
     * Prepares a new {@link NamingException} wrapping the specified
     * {@link RemoteException} source exception. Source exception becomes a
     * {@linkplain NamingException#getCause() cause} of the generated exception.
     *
     * The particular subclass of {@link NamingException} returned depends on
     * the particular subclass of source {@link RemoteException}.
     *
     * If source exception is not of a specific class or is not a
     * {@link RemoteException} or is <code>null</code>, then plain
     * {@link NamingException} is returned.
     *
     * Note: {@link Throwable#fillInStackTrace()} should be called before
     * throwing the generated exception, to provide the proper (not including
     * this method) stack trace for the exception.
     *
     * Example of use:
     *
     * <code>try {
     *     ...
     * } catch (RemoteException e) {
     *     throw (NamingException) newNamingException(e).fillInStackTrace();
     * }</code>
     *
     * @param e
     *            Source {@link RemoteException}.
     *
     * @return Generated {@link NamingException} exception.
     */
    @SuppressWarnings("deprecation")
    protected NamingException newNamingException(Throwable e) {
        NamingException ret = (e instanceof AccessException) ? new NoPermissionException()
                : (e instanceof ConnectException) ? new ServiceUnavailableException()
                        : (e instanceof ConnectIOException)
                                || (e instanceof ExportException)
                                || (e instanceof MarshalException)
                                || (e instanceof UnmarshalException) ? new CommunicationException()
                                : (e instanceof ActivateFailedException)
                                        || (e instanceof NoSuchObjectException)
                                        || (e instanceof java.rmi.server.SkeletonMismatchException)
                                        || (e instanceof java.rmi.server.SkeletonNotFoundException)
                                        || (e instanceof StubNotFoundException)
                                        || (e instanceof UnknownHostException) ? new ConfigurationException()
                                        : (e instanceof ServerException) ? newNamingException(e
                                                .getCause())
                                                : new NamingException();

        if (ret.getCause() == null) {
            ret.initCause(e);
        }
        return ret;
    }

    /**
     * Installs {@link RMISecurityManager} if it is not already installed.
     *
     * @throws NoPermissionException
     *             If security manager other than {@link RMISecurityManager} is
     *             installed and prohibits installing a new security manager.
     */
    protected void installSecurityManager() throws NoPermissionException {
        if (!(System.getSecurityManager() instanceof RMISecurityManager)) {
            try {
                System.setSecurityManager(new RMISecurityManager());
            } catch (SecurityException e) {
                // jndi.84=Cannot install RMISecurityManager
                throw (NoPermissionException) new NoPermissionException(
                        Messages.getString("jndi.84")).initCause(e); //$NON-NLS-1$
            }
        }
    }

    /**
     * Creates reference to the {@linkplain Registry RMI registry} located on
     * the specified host and port.
     *
     * @param host
     *            Host. If <code>null</code>, localhost is assumed. May not
     *            be <code>null</code> if <code>csf</code> is not
     *            <code>null</code>.
     *
     * @param port
     *            Port. If <code>0</code>, default registry port (<code>1099</code>)
     *            is assumed. May not be <code>0</code> if <code>csf</code>
     *            is not <code>null</code>.
     *
     * @param csf
     *            RMIClientSocketFactory that is used to create socket
     *            connections to the registry. If <code>null</code>, default
     *            socket factory is used. See
     *            {@link LocateRegistry#getRegistry(String, int, RMIClientSocketFactory)}.
     *
     * @return Registry reference.
     *
     * @throws NamingException
     *             If getting registry failed.
     */
    protected Registry getRegistry(String host, int port,
            RMIClientSocketFactory csf) throws NamingException {
        try {
            return ((csf != null) ? LocateRegistry.getRegistry(host, port, csf)
                    : ((host != null) ? ((port != 0) ? LocateRegistry
                            .getRegistry(host, port) : LocateRegistry
                            .getRegistry(host)) : ((port != 0) ? LocateRegistry
                            .getRegistry(port) : LocateRegistry.getRegistry())));
        } catch (RemoteException e) {
            throw (NamingException) new NamingException().initCause(e);
        }
    }

}
TOP

Related Classes of org.apache.harmony.jndi.provider.rmi.registry.RegistryContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.