Adding URL Support

 


URL Context Factory

A URL context factory is a special object factory that creates contexts for resolving URL strings. Like all object factories, it is a class that implements the ObjectFactory interface. A URL context factory must not only satisfy all of the requirements specified for object factories as stated in the Object Factories lesson. It also must adhere to the following rules.
  • A null object argument to getObjectInstance() means that the factory should create a context for resolving arbitrary URL strings of the scheme associated with the factory. For example, such an invocation on a factory for the ldap scheme would return a context that accepts arbitrary LDAP URL strings, such as "ldap://ldap.wiz.com/o=wiz,c=us" and "ldap://ldap.umich.edu/o=umich,c=us".
  • If the object argument to getObjectInstance() is a URL string (java.lang.String) of a scheme acceptable to that factory, then the factory should return an object (which might not necessarily be a context) identified by the URL string. For example, if getObjectInstance() is given the string "ldap://ldap.wiz.com/o=wiz,c=us", then it would return the object named by the DN "o=wiz, c=us" at the LDAP server ldap.wiz.com.
  • If the object argument to getObjectInstance() is an array of URL strings (java.lang.String[]), then the factory should return the object named by any one of the URL strings. All of the URL strings in the array are assumed to be equivalent in terms of the object to which they refer. Verification of whether the strings are, or need to be, equivalent is up to the factory. The order of the URL strings in the array is insignificant.
If the factory receives any other type of object argument to getObjectInstance(), then its behavior is implementation-dependent.

The first rule applies to supporting the resolution of URL strings from the InitialContext--this is described later in this lesson. The second and third rules apply to supporting the resolution of URL strings embedded in a Reference--this is also described later in this lesson. As indicated by the second and third rules, a URL context factory is not only a producer of context objects. It can produce any type of object named by a URL string.

 

 

Class Name's Naming Convention

The URL context factory's class name must use the following naming convention so that it can be located by the JNDI framework:
package_prefix.scheme_id.scheme_idURLContextFactory
where
  • package_prefix is a valid prefix for a package in the Java programming language and
  • scheme_id is the naming/directory service's URL scheme id (for example, ldap is the scheme id for services that support the LDAP).
For example, the class name tut.foo.fooURLContextFactory is for the foo URL scheme; it has the package prefix "tut". In another example, the class name com.sun.jndi.url.ldap.ldapURLContextFactory is for the ldap URL scheme; it has the package prefix "com.sun.jndi.url". Notice that package_prefix must not be empty.

 

 

Sample Implementation

This section offers an example of how to implement a URL context factory. This example is for illustrative purposes and is not meant to be prescriptive.

The example is for the foo URL scheme, which has the syntax

foo:name in the HierCtx namespace
HierCtx is an in-memory hierarchical namespace implementation. To make it work with the URL example, you need to create a static namespace that can be accessed by using a static method on the HierCtx class. Using a foo URL string, you can name the objects in this static namespace.

Like all object factories, a URL context factory must be public and have a public constructor that accepts no arguments.

public class fooURLContextFactory implements ObjectFactory {
    public fooURLContextFactory() {
    }
    ...
}

This factory's implementation of getObjectInstance() fairly well follows the three rules listed previously. The implementations of these rules use the following utility to create a context from the context implementation fooURLContext.

protected Context getURLContext(Hashtable env) {
    return new fooURLContext(env);
}
An actual implementation may or may not choose this strategy of using one context implementation to satisfy all three requirements. It is perfectly acceptable to have a factory that uses different context implementations.

In the following examples, urlInfo is the object argument to getObjectInstance().

For the first rule, you simply return the root fooURLContext.

if (urlInfo == null) {
    return createURLContext(env);
}

For the second rule, you use the root fooURLContext to look up and return the object named by the URL string.

if (urlInfo instanceof String) {
    Context urlCtx = createURLContext(env);
    try {
        return urlCtx.lookup((String)urlInfo);
    } finally {
        urlCtx.close();
    }
} 
Notice that before the method returns, it closes the root fooURLContext. In this particular example, this step is not really necessary because fooURLContext doesn't maintain any connections or resources. However, doing this is good practice so as to ensure that implementations that do maintain connections or resources are cleaned up properly.

For the third rule, you iterate over the array of URL strings until you find one that succeeds. You save one of the exceptions encountered along the way in case all of the URL strings fail and you need to indicate why.

if (urlInfo instanceof String[]) {

    // Try each URL until lookup() succeeds for one of them.
    // If all URLs fail, throw one of the exceptions arbitrarily.
    String[] urls = (String[])urlInfo;
    if (urls.length == 0) {
        throw (new ConfigurationException("fooURLContextFactory: empty URL array"));
    }
    Context urlCtx = createURLContext(env);
    try {
	NamingException ne = null;
	for (int i = 0; i < urls.length; i++) {
	    try {
	        return urlCtx.lookup(urls[i]);
	    } catch (NamingException e) {
	        ne = e;
	    }
        }
        throw ne;
    } finally {
        urlCtx.close();
    }
}

Adding URL Support