| Adding URL Support

## Relationship to the Initial Context

> When the API user supplies a URL string to one of the methods in the `InitialContext` or `InitialDirContext` class, the JNDI extracts the URL scheme from the string and uses `NamingManager.getURLContext()` to find a URL context implementation that can process the URL string. This method uses the algorithm described earlier in this lesson.

> If the JNDI successfully locates a URL context implementation, then it invokes the original context method by using the original arguments. This means that the complete URL string is passed on to the URL context implementation, where it is processed as described in the URL Context Implementation section of this lesson.

> If the JNDI cannot locate a URL context implementation to use to process the URL string, then it assumes that the input name is not a URL string. It then passes the name to the underlying initial context implementation (that named by the `Context.INITIAL_CONTEXT_FACTORY` (`"java.naming.factory.initial"`) environment property).

> #### Supporting Subinterfaces

> To provide URL support from the initial context to a `Context` subinterface, you need to define a new class that extends from `InitialContext` or one of its subclasses. See the discussion earlier in this lesson regarding factors to consider when deciding whether to add URL support for a subinterface.

> For example, suppose that `BarContext` extends `Context` by adding two new methods: `barMethod()`, which accepts a name argument, and `bazMethod()`, which does not. This service has a URL scheme id of `bar`. (See its URL context implementation presented earlier in this lesson.) To define an initial context for this interface, you first specify its inheritance.

> >     public class InitialBarContext
> >         extends InitialContext implements BarContext

> This class extends from the `InitialContext` and implements the new interface, `BarContext`.

> Then you define some constructors that are suitable for the class. Typically, you should plan on at least two constructors, one that accepts no arguments and one that accepts the environment parameter.

> >     public InitialBarContext() throws NamingException {
> >         super();
> >     }

> >     public InitialBarContext(Hashtable env) throws NamingException {
> >         super(env);
> >     }

> Next, you provide utility methods for both methods that process names and those that don't. For methods that process names, define a utility method that returns either a URL context or the default underlying initial context by inspecting the name argument. Most of the work for this is done by the protected method `InitialContext.getURLOrDefaultInitCtx()`. The utility method needs only to check the type of the resulting context to make sure that it is compatible with that of the subinterface. You need two such methods, one for the string name and one for `Name`. Here is the string version.

> >     protected BarContext getURLOrDefaultInitBarCtx(String name)
> >         throws NamingException {
> >         Context ctx = getURLOrDefaultInitCtx(name);
> >         if (!(ctx instanceof BarContext)) {
> >     	throw new NoInitialContextException("Not a BarContext");
> >         }
> >         return (BarContext)ctx;
> >     }

> For methods that do not process names, define a utility method that returns the default underlying initial context. Most of the work for this is done by the protected method `InitialContext.getDefaultInitCtx()`. The utility method needs only to check the type of the resulting context to make sure that it is compatible with that of the subinterface.

> >     protected BarContext getDefaultInitBarCtx() throws NamingException {
> >         Context ctx = getDefaultInitCtx();
> >         if (!(ctx instanceof BarContext)) {
> >     	throw new NoInitialContextException("Not a BarContext");
> >         }
> >         return (BarContext)ctx;
> >     }

> Once you have these methods, it is straightforward to provide implementations for all of the new methods. New name-related methods use `getURLOrDefaultInitBarCtx()`, whereas new non-name-related methods use `getDefaultInitBarCtx()`. Here are some examples.

> >     public Object barMethod(String name) throws NamingException {
> >         return getURLOrDefaultInitBarCtx(name).barMethod(name);
> >     }

> >     public String bazMethod() throws NamingException {
> >         return getDefaultInitBarCtx().bazMethod();
> >     }

> To use this new initial context implementation, your program must import the new class. Here is an example that invokes one of the new methods using a `bar` URL.

> >     tut.BarContext ctx = new tut.InitialBarContext();

> >     // Invoke the BarContext-specific method with the URL
> >     Object answer = ctx.barMethod("bar:/a");

> Running this example produces the output

> >     The answer is a

| Adding URL Support