| URLs

## URLs as Names to the Initial Context

> In the JNDI, every name is resolved relative to a context. To begin, you typically create an initial context by using one of the constructors from the `InitialContext`, `InitialDirContext`, or `InitialLdapContext` class. The Environment Properties lesson contains examples of how to use these constructors.

> Once you have an instance of a `Context`, you can look up other contexts and perform naming operations relative to those contexts. The names supplied to all of these contexts are relative names. That is, they are interpreted relative to the context to which they are supplied.

> The closest thing to an absolute name in the JNDI is a URL string. In the JNDI, you can supply a URL string to the methods in the `InitialContext` and `InitialDirContext` classes. (The `InitialLdapContext` class does not declare any method that accepts a name argument, although the class does inherit all of the methods from the `InitialContext` and `InitialDirContext` classes.)

> #### Client's View

> When you supply a URL string, that is, a string of the form

> > scheme : scheme-specific-parts

> to an `InitialContext` or `InitialDirContext` method, such as `lookup()`, the name is treated as a URL string rather than a name relative to the initial context. Here is an example that looks up an object using an LDAP URL string.

> >     Object obj = new InitialContext().lookup(
> >         "ldap://localhost:389/cn=homedir,cn=Jon Ruiz,ou=People,o=jnditutorial");

> The `InitialContext` class (and subclasses) diverts the method invocation so that it is processed by the corresponding URL context implementation rather than any underlying initial context implementation. That is, if you had set the `Context.INITIAL_CONTEXT_FACTORY` environment property, then it would not have been used in the `lookup()` call. Instead, the JNDI would find and use the URL context implementation for the `ldap` URL scheme. Notice from the previous example that no `Context.INITIAL_CONTEXT_FACTORY` property was specified to the `InitialContext` constructor.

> The JNDI's ability to accept arbitrary URL strings from the `InitialContext` class (and subclasses) allows you to access any namespace for which you have an implementation. Thus, you are not restricted by the namespace offered by the implementation named by the `Context.INITIAL_CONTEXT_FACTORY` property. For example, suppose that you name a file system service provider by using the `Context.INITIAL_CONTEXT_FACTORY` environment property. Using the same `InitialContext` instance, you can access an LDAP namespace by specifying an LDAP URL string and you can access a CORBA namespace by specifying a CORBA URL string.

> #### How URL Strings Are Processed

> When the `InitialContext` class receives a URL string as a name argument to one of its methods, it looks for a URL context implementation. It does this by using the `Context.URL_PKG_PREFIXES` environment property. This property contains a colon-separated list of package prefixes. Each item in the list is a fully qualified package prefix of a URL context factory. The factory name is constructed using the following rule:

> > package_prefix . scheme . scheme `URLContextFactory`

> The package prefix `"com.sun.jndi.url"` is always appended to the end of this list.

> Typically, a service provider that supplies a context implementation will also supply a URL context implementation so that it can handle URL strings passed to the `InitialContext`. However, this is not a requirement and some service providers might not supply any URL context implementations. Suppose that the `URL_PKG_PREFIXES` property contains

> >     com.widget:com.wiz.jndi

> Also suppose that the following URL string is supplied to the `lookup()` method of the `InitialContext` class:

> >     ldap://localhost:389/cn=homedir, cn=Jon Ruiz, ou=People, o=JNDITutorial

> The JNDI will then look for the following classes:

> >     com.widget.ldap.ldapURLContextFactory
> >     com.wiz.jndi.ldap.ldapURLContextFactory
> >     com.sun.jndi.url.ldap.ldapURLContextFactory

> It next tries to instantiate each class in turn and invokes `ObjectFactory.getObjectInstance(Object, Name, Context, Hashtable)` until one of them produces a non-`null` answer. The answer, which is a context, is then used to carry out the originally intended method, using the URL string as the name argument.

> Next, suppose that the JNDI successfully instantiated the `com.wiz.jndi.ldap.ldapURLContextFactory` class and obtains a context from it. The JNDI then invokes `lookup()` on the context and supply it `"ldap://localhost:389/cn=homedir, cn=Jon Ruiz, ou=People, o=JNDITutorial"` as the string name argument.

> If the JNDI cannot find a URL context factory that returns a non-`null` answer, then the input URL string is passed to the underlying initial context implementation (i.e., that implementation specified in the `Context.INITIAL_CONTEXT_FACTORY` environment property).

> See the Building a Service Provider trail for descriptions on how to write a URL context implementation.

> #### Relationship to the Underlying Initial Context

> You need to understand that no relationship exists between the implementation named by the `Context.INITIAL_CONTEXT_FACTORY` environment property and any URL context implementation other than all can be accessed via the same `InitialContext` instance. For example, suppose that you have the following environment property settings:

> >     java.naming.factory.initial=com.wiz.jndi.ldap.LdapContextFactory
> >     java.naming.factory.url.pkgs=

> If you supply the name `"ldap://localhost:389/o=JNDITutorial"` to `InitialContext.lookup()`, then the list of URL context factory classes that the JNDI will try is

> >     com.sun.jndi.url.ldap.ldapURLContextFactory

> If the service provider came with a URL context factory, then the provider should supply an application resource file (`jndi.properties`) that contains the factory's package prefix. See the Environment Properties lesson for a description of application resource files. If the provider has a URL context factory but has not specified a package prefix for it in an application resource file, then you should specify it in your program or application resource file so that the JNDI can find the factory.

> #### Relationship to Composite Names

> To specify a URL string as part of a composite name to the methods in the `InitialContext`, make it the first component of a composite name. By doing this, you, in effect, use the URL string to name a context in which to continue operation on the rest of the name's components.

> Here is an example that creates a `CompositeName` that consists of an LDAP URL string as the first component and filenames as the remaining components.

> >     String url =
> >         "ldap://localhost:389/cn=homedir,cn=Jon Ruiz,ou=people,o=JNDITutorial";

> >     // Create a CompositeName in which the first component is a URL string
> >     Name name = new CompositeName().add(url);

> >     // Add the other components
> >     name.add("tutorial").add("report.txt");

> >     // Perform the lookup by using CompositeName
> >     System.out.println(ctx.lookup(name));

> You can't specify composite name components as part of the URL string itself because doing so might conflict with the URL's syntax.

> #### More Than Just Names

> Some URLs, such as those for the LDAP (RFC 2255), specify more than name components. The LDAP URL syntax allows you to specify the scope of the search and the search query, as well as the attributes to return. See the Miscellaneous lesson for more information and an example of how query components in a URL string are used.

| URLs