JNDI/RMI Registry Service Provider

# RMI Registry Service Provider for the
Java Naming and Directory InterfaceTM (JNDI)

Please send feedback to jndi@java.sun.com

Table of Contents

- Introduction
- Environment Properties
- Names
- RMI URLs
- RMI URL Format
- API Mapping
- Bindings
- Usage Examples
- Security Considerations

## Introduction

The RMI registry service provider allows JNDI applications to access remote objects registered with the RMI registry. Given the location of a registry, the provider will create a naming context with bindings for the objects registered there. Such a context may be bound into another JNDI-accessible namespace (such as LDAP, for example). References to individual remote objects may likewise be bound into another namespace.

A key benefit of binding registry contexts into other namespaces is location-independent access to remote objects: the RMI clients do not need to know the registry's host name or port number. RMI servers can take advantage of this to advertise their services to potential clients. In addition, remote objects can be linked into the same enterprise directory that is used to access information about people, organizations, and network resources.

With this service provider installed, JNDI subsumes the functionality of the `java.rmi.Naming` class.

This document describes the features of the RMI registry service provider.

## Environment Properties

The following JNDI environment properties are used by the RMI registry service provider. See the JNDI documentation for a description of how properties are initialized using the environment properties, system properties, applet parameters, and resource files.

    java.naming.factory.initial

> This property is used to select the registry service provider as the initial context. It is not used by the provider itself. It specifies the class name of the initial context factory for the provider.

> For example:

> >     env.put(Context.INITIAL_CONTEXT_FACTORY,
> >         "com.sun.jndi.rmi.registry.RegistryContextFactory");

> This property is used in conjunction with the `java.naming.provider.url` property. This property must be set if you are using the registry as the initial context. The only exception is if you supply only URLs to the initial context, in which case, you don't need to specify this property. See RMI URLs for details.

    java.naming.provider.url

> This property specifies the location of the registry when the registry is being used as the initial context. It's value is an RMI URL with no object name component (see RMI URL Format below).

> For example:

> >     env.put(Context.PROVIDER_URL, "rmi://server:1099");

> The default value of this property is "rmi:", signifying a registry running on port 1099 of the local host.

> This property is used in conjunction with the `java.naming.factory.initial` property.

    java.naming.factory.state

> A colon-separated list of the fully qualified class names of state factory classes used to get an object's state for storing given the object itself. You can use this mechanism to transform an object into forms that can be stored into the registry. The RMI registry service provider supports storing `java.rmi.Remote`, `javax.naming.Reference`, and `javax.naming.Referenceable` objects. See `javax.naming.spi.NamingManager.getStateToBind()` for details.

    java.naming.factory.object

> A colon-separated list of the fully qualified class names of object factory classes for transforming objects read from the registry. You can use this mechanism to transform an object into forms expected by the application. See `javax.naming.spi.NamingManager.getObjectInstance()` for details.

    java.naming.rmi.security.manager

> This property, when set to any value, indicates that the provider should attempt to install the `RMISecurityManager`. See the Security Considerations section below.

## Names

The RMI registry supports a flat namespace. Since there is no hierarchy, every name is atomic. Each name may be composed of any characters, and case is significant.

Names are passed as arguments to the methods of a registry context, and are returned as the results of those methods, either as `Name` objects or as strings. When a `Name` object is used, it should have a single component whose value is the atomic name that will be passed on to the registry. When a string is used as a name, it is interpreted as the string representation of a composite name. So if `ctx` is a registry context, for example, then the following two unbind operations are equivalent:

>     String name = ...
>     ctx.unbind(name);
>     ctx.unbind(new CompositeName(name));

Care must be taken with names containing any of the four meta-characters that are treated specially during the parsing of composite names: '/', '\\', '"', and '\''. These characters must be properly escaped or quoted. The atomic name X/Y, for example, may be represented as the composite name X\/Y so as not to be mistaken for a two-component name with X and Y as its components. See `CompositeName` for more information.

## RMI URLs

JNDI provides support for resolving URLs that name objects. The registry service provider allows RMI URLs to be used as names in this manner. This provides a generalization of the `java.rmi.Naming` functionality, only using the more general JNDI interface.

The class `com.sun.jndi.url.rmi.rmiURLContextFactory` implements a URL context factory for RMI URLs. This allows an RMI URL to be passed as a name to the default JNDI initial context.

## RMI URL Format

The format of an RMI URL is one of the following:

       rmi://[host][:port][/[object]]

       rmi:[/][object]

If the object name is absent, then the URL names the registry at the given host and port. Otherwise, it names the remote object registered at that registry under the name provided.

If the host is omitted, the local host is assumed. If the port is omitted, the default registry port 1099 is assumed.

## API Mapping

The registry service provider implements the `java.naming.Context` and `java.naming.Referenceable` interfaces. `Context` and `Referenceable` methods are mapped onto registry operations as described below.

    lookup()
    lookupLink()

> The `java.rmi.Registry.lookup()` method is called. If the returned object is a wrapper around a `javax.naming.Reference`, the referenced object is created using `javax.naming.spi.NamingManager.getObjectInstance()`. JNDI links are not currently supported.

    bind()

> The `java.rmi.Registry.bind()` method is called. State factories are first consulted through `javax.naming.spi.NamingManager.getStateToBind()`. The object being bound must be of type `java.rmi.Remote`, `javax.naming.Reference`, or `javax.naming.Referenceable`. If the object is a `javax.naming.Reference` or `javax.naming.Referenceable`, its reference is wrapped in a `Remote` wrapper and then bound (see Binding Objects into the Registry below).

    rebind()

> The `java.rmi.Registry.rebind()` method is called. Objects are otherwise treated as for the JNDI `bind()` operation.

    unbind()

> The `java.rmi.Registry.unbind()` method is called.

    rename()

> This method is implemented as a sequence of JNDI operations: `lookup()`, `bind()`, `unbind()`. The sequence is not performed atomically.

    list()

> The `java.rmi.Registry.list()` method is called. As this provides no information about the types of the bound objects, each `javax.naming.NameClassPair` returned has the generic `java.lang.Object` as its class name.

    listBindings()

> The `java.rmi.Registry.list()` method is called. As each `javax.naming.Binding` is read from the resulting enumeration, `java.rmi.Registry.lookup()` is called and passed through `javax.naming.spi.NamingManager.getObjectInstance()`.

    createSubcontext()
    destroySubcontext()

> These operations are not supported.

    getNameParser()

> Returns a name parser for case-sensitive atomic names.

    getNameInNamespace()

> Returns the empty string (the name of the registry).

    composeName()

> Returns the composition of the two names.

    addToEnvironment()

> The specified property is added to the context's environment. If the `java.naming.rmi.security.manager` property is added, the provider will attempt to install the default RMI security manager (see Security Considerations). Other properties may be added or changed in the environment, but have no additional effect on the context.

    removeFromEnvironment()

> The specified property is removed from the context's environment. The context is otherwise unaffected.

    close()

> Clears internal state used by the provider, but otherwise has no immediate effect.

    getReference()

> If this context was constructed from a reference, a clone of that reference is returned. Otherwise a new reference for the context is returned, providing that the host name can be determined and is not "localhost" (see Binding Registry Contexts and Remote Objects below).

## Bindings

Binding Objects into the Registry

An object may be bound into a registry context if it implements the `java.rmi.Remote` interface. An object may also be bound if it is a JNDI Reference object, or if it implements the `Referenceable` interface (in which case the corresponding reference will be bound in place of the object itself).

Binding Registry Contexts and Remote Objects

Each RMI registry context implements the `Referenceable` interface. It may therefore be bound into any JNDI-accessible namespace that can store `Referenceable` objects. A reference to an individual remote object that is registered with a registry may also be constructed, allowing that object to be bound into another namespace.

The class `com.sun.jndi.rmi.registry.RegistryContextFactory` implements the object factory that converts registry references into the corresponding registry contexts or remote objects.

For a registry context to be constructed, the registry's URL must be determined. This URL may come from the `java.naming.provider.url` property, or may be passed as a name to the initial context, or may be embedded in a registry reference. If the URL contains no host name or uses the host name "localhost", then the registry context's `getReference()` method is unable to return a reference for the context. Such a registry context, therefore, cannot be bound into another namespace.

Registry Reference Format

A JNDI reference for an RMI registry contains a list of string addresses (class `StringRefAddr`), each tagged with the type "URL". Each address contains an RMI URL locating either a registry, or a remote object registered with a registry (see RMI URL Format above).

When multiple URLs appear within a single reference, each represents an alternative address for the same logical resource. The order of the addresses is not significant. Addresses not of class `StringRefAddr`, or not of address type "URL", are ignored.

## Usage Examples

Example 1

To create an initial context that accesses a registry, set the properties `java.naming.factory.initial` and `java.naming.provider.url` as described in Environment Properties above. Then the names stored in the registry, for example, may be listed as follows:

>     Context ictx = new InitialContext(env);
>     NamingEnumeration enum = ictx.list("");

Example 2

Instead of using the properties as above, you may pass an RMI URL as a name to resolve in the default initial context:

>     Context registryCtx = (Context)ictx.lookup("rmi://host");

Example 3

A registry context may be bound into another JNDI-accessible namespace. To bind `registryCtx` (from the preceding example) into an LDAP directory, for example:

>     Context ldapCtx = (Context)ictx.lookup("ldap://server/o=sun,c=us");
>     ldapCtx.bind("cn=rmi", registryCtx);

If the names R1 and R2 are bound in this registry, then a JNDI client browsing the LDAP namespace will see R1 and R2 beneath the cn=rmi entry.

Example 4

A remote object that is registered with an RMI registry may be bound into another JNDI-accessible namespace by constructing a reference for that object. If the variable `obj` holds the object named R1 from the preceding examples, it may be bound into an LDAP directory as follows:

>     RefAddr addr = new StringRefAddr("URL", "rmi://host/R1");
>     Reference ref = new Reference(obj.getClass().getName(), addr);
>     ldapCtx.bind("cn=R1", ref);

## Security Considerations

#### Security Manager

The usual security considerations of RMI apply. For RMI to dynamically load classes from a remote server, a security manager must first be installed. This can be done in the same way as it would for any other RMI application. See the JavaTM Remote Method Invocation Specification. Or, if the environment property `java.naming.rmi.security.manager` is passed to the provider, then the provider will attempt to install the `RMISecurityManager` itself.

#### Permissions

The application using JNDI and the RMI registry provider must be granted the following permissions:

    permission java.net.SocketPermission "host[:port]", "connect";

> For each host/port identified in the `java.naming.provider.url` property and in URL string names supplied to context methods.

    permission java.net.SocketPermission "host[:port]", "connect,accept";

> For each host/port identified in the URL strings in `javax.naming.Reference`s.

    permission java.lang.RuntimePermission "setSecurityManager";

> If using the `java.naming.rmi.security.manager` environment property, which asks the RMI registry provider to install the `RMISecurityManager`.

Copyright © 1999-2001 Sun Microsystems, Inc., All Rights Reserved.