The Ground Rules
Environment Properties
Environment properties and how they are used by the application are described in detail in the Environment Properties lesson. This section describes how a service provider should handle environment properties.
Initialization When a program uses the constructors from the InitialContext class or its subclasses, it supplies an optional environment parameter. The JNDI class libraries merge the contents of this parameter with other sources of environment properties (see the Environment Properties lesson) and give the result to the service provider. More precisely, the JNDI gives the result to InitialContextFactory.getInitialContext(), which in turns creates the context implementation and supplies the resulting environment properties as a parameter. The context implementation does not have to worry about where the properties came from or with consulting the various sources. The JNDI class libraries will fetch and merge the properties before giving them to the underlying context implementation.
Ownership Typically, the context implementation needs to remember the contents of the environment beyond initialization of the context implementation. At a minimum, the context implementation needs the environment for processing Context.getEnvironment(). Like all other parameters received by a context implementation, the environment properties are owned by the caller and not by the context implementation. Therefore the context implementation needs to make a copy of the environment.
A common pattern in the context implementation's constructor is one that clones the environment, illustrated as follows.
if (inEnv != null) { myEnv = (Hashtable)inEnv.clone(); } else { myEnv = new Hashtable(); }
Inheritance A Context instance is said to be derived from another Context instance if the latter was involved in the creation of the former. For example, if you obtain Context instance B by performing a Context.lookup() on Context instance A, then instance B is derived from instance A. Similarly, if you list a context and obtain a bunch of other Context instances, those other instances are derived from the listed context.
A Context instance inherits its environment from the context from which it was derived, even across naming system boundaries. Following are the three places where a context implementation should pass on its environment.
Note that inheritance occurs at the point at which the derived Context instance is created. Inheritance does not mean sharing. Each Context instance must maintain its own environment in such a way that any changes to its environment do not affect the environment of other Context instances.
- When a context implementation creates a Context instance, it should pass the parent Context instance's environment to the newly created Context instance. This can be done by cloning the environment or by using a copy-on-write policy so that each context's environment maintains its independence.
- When a context implementation invokes any of the following methods, it should pass the context's environment.
The factory, or Context instance derived from the factory, resulting from these calls is responsible for cloning the environment as needed.
- NamingManager.getObjectInstance(Object, Name, Context, Hashtable)
- DirectoryManager.getObjectInstance(Object, Name, Context, Hashtable, Attributes)
- NamingManager.getStateToBind(Object, Name, Context, Hashtable)
- DirectoryManager.getStateToBind(Object, Name, Context, Hashtable, Attributes)
- ControlFactory.getControlInstance(Control, Context, Hashtable)
- When a context implementation that supports federation reaches its naming system boundary, it constructs a CannotProceedException that pinpoints how far it has gotten and then invokes NamingManager.getContinuationContext() or DirectoryManager.getContinuationDirContext(). The context implementation should invoke CannotProceedException.setEnvironment() with the context's environment. Doing this passes the context's environment to the continuation context in the nns (next naming system). The context in the nns is responsible for cloning the environment as needed.
Applicability Possibly not all of the environment properties passed to a context will apply to that context implementation. The implementation is responsible for selecting and using those properties that apply to it and for maintaining and ignoring the ones that don't. The context is responsible for passing all properties, including those that it does not use, to Context instances derived from it. This allows the application to set up in one place the environment properties for all of the context implementations with which it will be interacting, instead of just those for the initial context.
Provider Resource Files The JNDI SPI methods listed previously (getObjectInstance(), getStateToBind(), and getControlInstance()) not only use the properties found in the environment parameter, but also the context implementation's provider resource file. The JNDI locates the provider resource file by using the Context parameter. The name of the provider resource file is
[prefix/]jndiprovider.propertieswhere prefix is the package name of the Context parameter and each period character (".") is converted to a forward slash character ("/"). For example, suppose that the Context parameter is an instance of the class com.sun.jndi.ldap.LdapCtx. Its provider resource file will named com/sun/jndi/ldap/jndiprovider.properties.The JNDI SPI methods consult the provider resource file when determining the values of the following properties:
These values are appended to the values found in the environment parameter.java.naming.factory.object java.naming.factory.state java.naming.factory.control java.naming.factory.url.pkgsProperties other than these may be set in the provider resource file at the service provider's discretion. These additional properties are ignored by the JNDI but might be used by the service provider. If your provider uses additional properties from the provider resource file, then you should document them clearly.
Provider-Specific Properties The Environment Properties lesson discusses the different categories of environment properties. Provider-specific environment properties are used only by a specific service provider. Before you define a provider-specific environment property, you should ensure that it must be provider-specific and cannot be service- or feature-specific. See the Environment Properties lesson for information on how to categorize environment properties.
When defining a provider-specific property, you should prefix it with the package name of your service provider. For example, if your context implementation has the class name com.sun.jndi.ldap.LdapCtx, then its provider-specific properties should have the prefix "com.sun.jndi.ldap.".
The Ground Rules