Save This Page
Home » openjdk-7 » javax » naming » spi » [javadoc | source]
    1   /*
    2    * Copyright 1999-2004 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.naming.spi;
   27   
   28   import java.util.Enumeration;
   29   import java.util.Hashtable;
   30   import java.util.StringTokenizer;
   31   import java.net.MalformedURLException;
   32   
   33   import javax.naming;
   34   import com.sun.naming.internal.VersionHelper;
   35   import com.sun.naming.internal.ResourceManager;
   36   import com.sun.naming.internal.FactoryEnumeration;
   37   
   38   /**
   39    * This class contains methods for creating context objects
   40    * and objects referred to by location information in the naming
   41    * or directory service.
   42    *<p>
   43    * This class cannot be instantiated.  It has only static methods.
   44    *<p>
   45    * The mention of URL in the documentation for this class refers to
   46    * a URL string as defined by RFC 1738 and its related RFCs. It is
   47    * any string that conforms to the syntax described therein, and
   48    * may not always have corresponding support in the java.net.URL
   49    * class or Web browsers.
   50    *<p>
   51    * NamingManager is safe for concurrent access by multiple threads.
   52    *<p>
   53    * Except as otherwise noted,
   54    * a <tt>Name</tt> or environment parameter
   55    * passed to any method is owned by the caller.
   56    * The implementation will not modify the object or keep a reference
   57    * to it, although it may keep a reference to a clone or copy.
   58    *
   59    * @author Rosanna Lee
   60    * @author Scott Seligman
   61    * @since 1.3
   62    */
   63   
   64   public class NamingManager {
   65   
   66       /*
   67        * Disallow anyone from creating one of these.
   68        * Made package private so that DirectoryManager can subclass.
   69        */
   70   
   71       NamingManager() {}
   72   
   73       // should be protected and package private
   74       static final VersionHelper helper = VersionHelper.getVersionHelper();
   75   
   76   // --------- object factory stuff
   77   
   78       /**
   79        * Package-private; used by DirectoryManager and NamingManager.
   80        */
   81       private static ObjectFactoryBuilder object_factory_builder = null;
   82   
   83       /**
   84        * The ObjectFactoryBuilder determines the policy used when
   85        * trying to load object factories.
   86        * See getObjectInstance() and class ObjectFactory for a description
   87        * of the default policy.
   88        * setObjectFactoryBuilder() overrides this default policy by installing
   89        * an ObjectFactoryBuilder. Subsequent object factories will
   90        * be loaded and created using the installed builder.
   91        *<p>
   92        * The builder can only be installed if the executing thread is allowed
   93        * (by the security manager's checkSetFactory() method) to do so.
   94        * Once installed, the builder cannot be replaced.
   95        *<p>
   96        * @param builder The factory builder to install. If null, no builder
   97        *                  is installed.
   98        * @exception SecurityException builder cannot be installed
   99        *          for security reasons.
  100        * @exception NamingException builder cannot be installed for
  101        *         a non-security-related reason.
  102        * @exception IllegalStateException If a factory has already been installed.
  103        * @see #getObjectInstance
  104        * @see ObjectFactory
  105        * @see ObjectFactoryBuilder
  106        * @see java.lang.SecurityManager#checkSetFactory
  107        */
  108       public static synchronized void setObjectFactoryBuilder(
  109               ObjectFactoryBuilder builder) throws NamingException {
  110           if (object_factory_builder != null)
  111               throw new IllegalStateException("ObjectFactoryBuilder already set");
  112   
  113           SecurityManager security = System.getSecurityManager();
  114           if (security != null) {
  115               security.checkSetFactory();
  116           }
  117           object_factory_builder = builder;
  118       }
  119   
  120       /**
  121        * Used for accessing object factory builder.
  122        */
  123       static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() {
  124           return object_factory_builder;
  125       }
  126   
  127   
  128       /**
  129        * Retrieves the ObjectFactory for the object identified by a reference,
  130        * using the reference's factory class name and factory codebase
  131        * to load in the factory's class.
  132        * @param ref The non-null reference to use.
  133        * @param factoryName The non-null class name of the factory.
  134        * @return The object factory for the object identified by ref; null
  135        * if unable to load the factory.
  136        */
  137       static ObjectFactory getObjectFactoryFromReference(
  138           Reference ref, String factoryName)
  139           throws IllegalAccessException,
  140           InstantiationException,
  141           MalformedURLException {
  142           Class clas = null;
  143   
  144           // Try to use current class loader
  145           try {
  146                clas = helper.loadClass(factoryName);
  147           } catch (ClassNotFoundException e) {
  148               // ignore and continue
  149               // e.printStackTrace();
  150           }
  151           // All other exceptions are passed up.
  152   
  153           // Not in class path; try to use codebase
  154           String codebase;
  155           if (clas == null &&
  156                   (codebase = ref.getFactoryClassLocation()) != null) {
  157               try {
  158                   clas = helper.loadClass(factoryName, codebase);
  159               } catch (ClassNotFoundException e) {
  160               }
  161           }
  162   
  163           return (clas != null) ? (ObjectFactory) clas.newInstance() : null;
  164       }
  165   
  166   
  167       /**
  168        * Creates an object using the factories specified in the
  169        * <tt>Context.OBJECT_FACTORIES</tt> property of the environment
  170        * or of the provider resource file associated with <tt>nameCtx</tt>.
  171        *
  172        * @return factory created; null if cannot create
  173        */
  174       private static Object createObjectFromFactories(Object obj, Name name,
  175               Context nameCtx, Hashtable environment) throws Exception {
  176   
  177           FactoryEnumeration factories = ResourceManager.getFactories(
  178               Context.OBJECT_FACTORIES, environment, nameCtx);
  179   
  180           if (factories == null)
  181               return null;
  182   
  183           // Try each factory until one succeeds
  184           ObjectFactory factory;
  185           Object answer = null;
  186           while (answer == null && factories.hasMore()) {
  187               factory = (ObjectFactory)factories.next();
  188               answer = factory.getObjectInstance(obj, name, nameCtx, environment);
  189           }
  190           return answer;
  191       }
  192   
  193       private static String getURLScheme(String str) {
  194           int colon_posn = str.indexOf(':');
  195           int slash_posn = str.indexOf('/');
  196   
  197           if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
  198               return str.substring(0, colon_posn);
  199           return null;
  200       }
  201   
  202       /**
  203        * Creates an instance of an object for the specified object
  204        * and environment.
  205        * <p>
  206        * If an object factory builder has been installed, it is used to
  207        * create a factory for creating the object.
  208        * Otherwise, the following rules are used to create the object:
  209        *<ol>
  210        * <li>If <code>refInfo</code> is a <code>Reference</code>
  211        *    or <code>Referenceable</code> containing a factory class name,
  212        *    use the named factory to create the object.
  213        *    Return <code>refInfo</code> if the factory cannot be created.
  214        *    Under JDK 1.1, if the factory class must be loaded from a location
  215        *    specified in the reference, a <tt>SecurityManager</tt> must have
  216        *    been installed or the factory creation will fail.
  217        *    If an exception is encountered while creating the factory,
  218        *    it is passed up to the caller.
  219        * <li>If <tt>refInfo</tt> is a <tt>Reference</tt> or
  220        *    <tt>Referenceable</tt> with no factory class name,
  221        *    and the address or addresses are <tt>StringRefAddr</tt>s with
  222        *    address type "URL",
  223        *    try the URL context factory corresponding to each URL's scheme id
  224        *    to create the object (see <tt>getURLContext()</tt>).
  225        *    If that fails, continue to the next step.
  226        * <li> Use the object factories specified in
  227        *    the <tt>Context.OBJECT_FACTORIES</tt> property of the environment,
  228        *    and of the provider resource file associated with
  229        *    <tt>nameCtx</tt>, in that order.
  230        *    The value of this property is a colon-separated list of factory
  231        *    class names that are tried in order, and the first one that succeeds
  232        *    in creating an object is the one used.
  233        *    If none of the factories can be loaded,
  234        *    return <code>refInfo</code>.
  235        *    If an exception is encountered while creating the object, the
  236        *    exception is passed up to the caller.
  237        *</ol>
  238        *<p>
  239        * Service providers that implement the <tt>DirContext</tt>
  240        * interface should use
  241        * <tt>DirectoryManager.getObjectInstance()</tt>, not this method.
  242        * Service providers that implement only the <tt>Context</tt>
  243        * interface should use this method.
  244        * <p>
  245        * Note that an object factory (an object that implements the ObjectFactory
  246        * interface) must be public and must have a public constructor that
  247        * accepts no arguments.
  248        * <p>
  249        * The <code>name</code> and <code>nameCtx</code> parameters may
  250        * optionally be used to specify the name of the object being created.
  251        * <code>name</code> is the name of the object, relative to context
  252        * <code>nameCtx</code>.  This information could be useful to the object
  253        * factory or to the object implementation.
  254        *  If there are several possible contexts from which the object
  255        *  could be named -- as will often be the case -- it is up to
  256        *  the caller to select one.  A good rule of thumb is to select the
  257        * "deepest" context available.
  258        * If <code>nameCtx</code> is null, <code>name</code> is relative
  259        * to the default initial context.  If no name is being specified, the
  260        * <code>name</code> parameter should be null.
  261        *
  262        * @param refInfo The possibly null object for which to create an object.
  263        * @param name The name of this object relative to <code>nameCtx</code>.
  264        *          Specifying a name is optional; if it is
  265        *          omitted, <code>name</code> should be null.
  266        * @param nameCtx The context relative to which the <code>name</code>
  267        *          parameter is specified.  If null, <code>name</code> is
  268        *          relative to the default initial context.
  269        * @param environment The possibly null environment to
  270        *          be used in the creation of the object factory and the object.
  271        * @return An object created using <code>refInfo</code>; or
  272        *          <code>refInfo</code> if an object cannot be created using
  273        *          the algorithm described above.
  274        * @exception NamingException if a naming exception was encountered
  275        *  while attempting to get a URL context, or if one of the
  276        *          factories accessed throws a NamingException.
  277        * @exception Exception if one of the factories accessed throws an
  278        *          exception, or if an error was encountered while loading
  279        *          and instantiating the factory and object classes.
  280        *          A factory should only throw an exception if it does not want
  281        *          other factories to be used in an attempt to create an object.
  282        *  See ObjectFactory.getObjectInstance().
  283        * @see #getURLContext
  284        * @see ObjectFactory
  285        * @see ObjectFactory#getObjectInstance
  286        */
  287       public static Object
  288           getObjectInstance(Object refInfo, Name name, Context nameCtx,
  289                             Hashtable<?,?> environment)
  290           throws Exception
  291       {
  292   
  293           ObjectFactory factory;
  294   
  295           // Use builder if installed
  296           ObjectFactoryBuilder builder = getObjectFactoryBuilder();
  297           if (builder != null) {
  298               // builder must return non-null factory
  299               factory = builder.createObjectFactory(refInfo, environment);
  300               return factory.getObjectInstance(refInfo, name, nameCtx,
  301                   environment);
  302           }
  303   
  304           // Use reference if possible
  305           Reference ref = null;
  306           if (refInfo instanceof Reference) {
  307               ref = (Reference) refInfo;
  308           } else if (refInfo instanceof Referenceable) {
  309               ref = ((Referenceable)(refInfo)).getReference();
  310           }
  311   
  312           Object answer;
  313   
  314           if (ref != null) {
  315               String f = ref.getFactoryClassName();
  316               if (f != null) {
  317                   // if reference identifies a factory, use exclusively
  318   
  319                   factory = getObjectFactoryFromReference(ref, f);
  320                   if (factory != null) {
  321                       return factory.getObjectInstance(ref, name, nameCtx,
  322                                                        environment);
  323                   }
  324                   // No factory found, so return original refInfo.
  325                   // Will reach this point if factory class is not in
  326                   // class path and reference does not contain a URL for it
  327                   return refInfo;
  328   
  329               } else {
  330                   // if reference has no factory, check for addresses
  331                   // containing URLs
  332   
  333                   answer = processURLAddrs(ref, name, nameCtx, environment);
  334                   if (answer != null) {
  335                       return answer;
  336                   }
  337               }
  338           }
  339   
  340           // try using any specified factories
  341           answer =
  342               createObjectFromFactories(refInfo, name, nameCtx, environment);
  343           return (answer != null) ? answer : refInfo;
  344       }
  345   
  346       /*
  347        * Ref has no factory.  For each address of type "URL", try its URL
  348        * context factory.  Returns null if unsuccessful in creating and
  349        * invoking a factory.
  350        */
  351       static Object processURLAddrs(Reference ref, Name name, Context nameCtx,
  352                                     Hashtable environment)
  353               throws NamingException {
  354   
  355           for (int i = 0; i < ref.size(); i++) {
  356               RefAddr addr = ref.get(i);
  357               if (addr instanceof StringRefAddr &&
  358                   addr.getType().equalsIgnoreCase("URL")) {
  359   
  360                   String url = (String)addr.getContent();
  361                   Object answer = processURL(url, name, nameCtx, environment);
  362                   if (answer != null) {
  363                       return answer;
  364                   }
  365               }
  366           }
  367           return null;
  368       }
  369   
  370       private static Object processURL(Object refInfo, Name name,
  371                                        Context nameCtx, Hashtable environment)
  372               throws NamingException {
  373           Object answer;
  374   
  375           // If refInfo is a URL string, try to use its URL context factory
  376           // If no context found, continue to try object factories.
  377           if (refInfo instanceof String) {
  378               String url = (String)refInfo;
  379               String scheme = getURLScheme(url);
  380               if (scheme != null) {
  381                   answer = getURLObject(scheme, refInfo, name, nameCtx,
  382                                         environment);
  383                   if (answer != null) {
  384                       return answer;
  385                   }
  386               }
  387           }
  388   
  389           // If refInfo is an array of URL strings,
  390           // try to find a context factory for any one of its URLs.
  391           // If no context found, continue to try object factories.
  392           if (refInfo instanceof String[]) {
  393               String[] urls = (String[])refInfo;
  394               for (int i = 0; i <urls.length; i++) {
  395                   String scheme = getURLScheme(urls[i]);
  396                   if (scheme != null) {
  397                       answer = getURLObject(scheme, refInfo, name, nameCtx,
  398                                             environment);
  399                       if (answer != null)
  400                           return answer;
  401                   }
  402               }
  403           }
  404           return null;
  405       }
  406   
  407   
  408       /**
  409        * Retrieves a context identified by <code>obj</code>, using the specified
  410        * environment.
  411        * Used by ContinuationContext.
  412        *
  413        * @param obj       The object identifying the context.
  414        * @param name      The name of the context being returned, relative to
  415        *                  <code>nameCtx</code>, or null if no name is being
  416        *                  specified.
  417        *                  See the <code>getObjectInstance</code> method for
  418        *                  details.
  419        * @param ctx       The context relative to which <code>name</code> is
  420        *                  specified, or null for the default initial context.
  421        *                  See the <code>getObjectInstance</code> method for
  422        *                  details.
  423        * @param environment Environment specifying characteristics of the
  424        *                  resulting context.
  425        * @return A context identified by <code>obj</code>.
  426        *
  427        * @see #getObjectInstance
  428        */
  429       static Context getContext(Object obj, Name name, Context nameCtx,
  430                                 Hashtable environment) throws NamingException {
  431           Object answer;
  432   
  433           if (obj instanceof Context) {
  434               // %%% Ignore environment for now.  OK since method not public.
  435               return (Context)obj;
  436           }
  437   
  438           try {
  439               answer = getObjectInstance(obj, name, nameCtx, environment);
  440           } catch (NamingException e) {
  441               throw e;
  442           } catch (Exception e) {
  443               NamingException ne = new NamingException();
  444               ne.setRootCause(e);
  445               throw ne;
  446           }
  447   
  448           return (answer instanceof Context)
  449               ? (Context)answer
  450               : null;
  451       }
  452   
  453       // Used by ContinuationContext
  454       static Resolver getResolver(Object obj, Name name, Context nameCtx,
  455                                   Hashtable environment) throws NamingException {
  456           Object answer;
  457   
  458           if (obj instanceof Resolver) {
  459               // %%% Ignore environment for now.  OK since method not public.
  460               return (Resolver)obj;
  461           }
  462   
  463           try {
  464               answer = getObjectInstance(obj, name, nameCtx, environment);
  465           } catch (NamingException e) {
  466               throw e;
  467           } catch (Exception e) {
  468               NamingException ne = new NamingException();
  469               ne.setRootCause(e);
  470               throw ne;
  471           }
  472   
  473           return (answer instanceof Resolver)
  474               ? (Resolver)answer
  475               : null;
  476       }
  477   
  478   
  479       /***************** URL Context implementations ***************/
  480   
  481       /**
  482        * Creates a context for the given URL scheme id.
  483        * <p>
  484        * The resulting context is for resolving URLs of the
  485        * scheme <code>scheme</code>. The resulting context is not tied
  486        * to a specific URL. It is able to handle arbitrary URLs with
  487        * the specified scheme.
  488        *<p>
  489        * The class name of the factory that creates the resulting context
  490        * has the naming convention <i>scheme-id</i>URLContextFactory
  491        * (e.g. "ftpURLContextFactory" for the "ftp" scheme-id),
  492        * in the package specified as follows.
  493        * The <tt>Context.URL_PKG_PREFIXES</tt> environment property (which
  494        * may contain values taken from applet parameters, system properties,
  495        * or application resource files)
  496        * contains a colon-separated list of package prefixes.
  497        * Each package prefix in
  498        * the property is tried in the order specified to load the factory class.
  499        * The default package prefix is "com.sun.jndi.url" (if none of the
  500        * specified packages work, this default is tried).
  501        * The complete package name is constructed using the package prefix,
  502        * concatenated with the scheme id.
  503        *<p>
  504        * For example, if the scheme id is "ldap", and the
  505        * <tt>Context.URL_PKG_PREFIXES</tt> property
  506        * contains "com.widget:com.wiz.jndi",
  507        * the naming manager would attempt to load the following classes
  508        * until one is successfully instantiated:
  509        *<ul>
  510        * <li>com.widget.ldap.ldapURLContextFactory
  511        *  <li>com.wiz.jndi.ldap.ldapURLContextFactory
  512        *  <li>com.sun.jndi.url.ldap.ldapURLContextFactory
  513        *</ul>
  514        * If none of the package prefixes work, null is returned.
  515        *<p>
  516        * If a factory is instantiated, it is invoked with the following
  517        * parameters to produce the resulting context.
  518        * <p>
  519        * <code>factory.getObjectInstance(null, environment);</code>
  520        * <p>
  521        * For example, invoking getObjectInstance() as shown above
  522        * on a LDAP URL context factory would return a
  523        * context that can resolve LDAP urls
  524        * (e.g. "ldap://ldap.wiz.com/o=wiz,c=us",
  525        * "ldap://ldap.umich.edu/o=umich,c=us", ...).
  526        *<p>
  527        * Note that an object factory (an object that implements the ObjectFactory
  528        * interface) must be public and must have a public constructor that
  529        * accepts no arguments.
  530        *
  531        * @param scheme    The non-null scheme-id of the URLs supported by the context.
  532        * @param environment The possibly null environment properties to be
  533        *           used in the creation of the object factory and the context.
  534        * @return A context for resolving URLs with the
  535        *         scheme id <code>scheme</code>;
  536        *  <code>null</code> if the factory for creating the
  537        *         context is not found.
  538        * @exception NamingException If a naming exception occurs while creating
  539        *          the context.
  540        * @see #getObjectInstance
  541        * @see ObjectFactory#getObjectInstance
  542        */
  543       public static Context getURLContext(String scheme,
  544                                           Hashtable<?,?> environment)
  545           throws NamingException
  546       {
  547           // pass in 'null' to indicate creation of generic context for scheme
  548           // (i.e. not specific to a URL).
  549   
  550               Object answer = getURLObject(scheme, null, null, null, environment);
  551               if (answer instanceof Context) {
  552                   return (Context)answer;
  553               } else {
  554                   return null;
  555               }
  556       }
  557   
  558       private static final String defaultPkgPrefix = "com.sun.jndi.url";
  559   
  560       /**
  561        * Creates an object for the given URL scheme id using
  562        * the supplied urlInfo.
  563        * <p>
  564        * If urlInfo is null, the result is a context for resolving URLs
  565        * with the scheme id 'scheme'.
  566        * If urlInfo is a URL, the result is a context named by the URL.
  567        * Names passed to this context is assumed to be relative to this
  568        * context (i.e. not a URL). For example, if urlInfo is
  569        * "ldap://ldap.wiz.com/o=Wiz,c=us", the resulting context will
  570        * be that pointed to by "o=Wiz,c=us" on the server 'ldap.wiz.com'.
  571        * Subsequent names that can be passed to this context will be
  572        * LDAP names relative to this context (e.g. cn="Barbs Jensen").
  573        * If urlInfo is an array of URLs, the URLs are assumed
  574        * to be equivalent in terms of the context to which they refer.
  575        * The resulting context is like that of the single URL case.
  576        * If urlInfo is of any other type, that is handled by the
  577        * context factory for the URL scheme.
  578        * @param scheme the URL scheme id for the context
  579        * @param urlInfo information used to create the context
  580        * @param name name of this object relative to <code>nameCtx</code>
  581        * @param nameCtx Context whose provider resource file will be searched
  582        *          for package prefix values (or null if none)
  583        * @param environment Environment properties for creating the context
  584        * @see javax.naming.InitialContext
  585        */
  586       private static Object getURLObject(String scheme, Object urlInfo,
  587                                          Name name, Context nameCtx,
  588                                          Hashtable environment)
  589               throws NamingException {
  590   
  591           // e.g. "ftpURLContextFactory"
  592           ObjectFactory factory = (ObjectFactory)ResourceManager.getFactory(
  593               Context.URL_PKG_PREFIXES, environment, nameCtx,
  594               "." + scheme + "." + scheme + "URLContextFactory", defaultPkgPrefix);
  595   
  596           if (factory == null)
  597             return null;
  598   
  599           // Found object factory
  600           try {
  601               return factory.getObjectInstance(urlInfo, name, nameCtx, environment);
  602           } catch (NamingException e) {
  603               throw e;
  604           } catch (Exception e) {
  605               NamingException ne = new NamingException();
  606               ne.setRootCause(e);
  607               throw ne;
  608           }
  609   
  610       }
  611   
  612   
  613   // ------------ Initial Context Factory Stuff
  614       private static InitialContextFactoryBuilder initctx_factory_builder = null;
  615   
  616       /**
  617        * Use this method for accessing initctx_factory_builder while
  618        * inside an unsynchronized method.
  619        */
  620       private static synchronized InitialContextFactoryBuilder
  621       getInitialContextFactoryBuilder() {
  622           return initctx_factory_builder;
  623       }
  624   
  625       /**
  626        * Creates an initial context using the specified environment
  627        * properties.
  628        *<p>
  629        * If an InitialContextFactoryBuilder has been installed,
  630        * it is used to create the factory for creating the initial context.
  631        * Otherwise, the class specified in the
  632        * <tt>Context.INITIAL_CONTEXT_FACTORY</tt> environment property is used.
  633        * Note that an initial context factory (an object that implements the
  634        * InitialContextFactory interface) must be public and must have a
  635        * public constructor that accepts no arguments.
  636        *
  637        * @param env The possibly null environment properties used when
  638        *                  creating the context.
  639        * @return A non-null initial context.
  640        * @exception NoInitialContextException If the
  641        *          <tt>Context.INITIAL_CONTEXT_FACTORY</tt> property
  642        *         is not found or names a nonexistent
  643        *         class or a class that cannot be instantiated,
  644        *          or if the initial context could not be created for some other
  645        *          reason.
  646        * @exception NamingException If some other naming exception was encountered.
  647        * @see javax.naming.InitialContext
  648        * @see javax.naming.directory.InitialDirContext
  649        */
  650       public static Context getInitialContext(Hashtable<?,?> env)
  651           throws NamingException {
  652           InitialContextFactory factory;
  653   
  654           InitialContextFactoryBuilder builder = getInitialContextFactoryBuilder();
  655           if (builder == null) {
  656               // No factory installed, use property
  657               // Get initial context factory class name
  658   
  659               String className = env != null ?
  660                   (String)env.get(Context.INITIAL_CONTEXT_FACTORY) : null;
  661               if (className == null) {
  662                   NoInitialContextException ne = new NoInitialContextException(
  663                       "Need to specify class name in environment or system " +
  664                       "property, or as an applet parameter, or in an " +
  665                       "application resource file:  " +
  666                       Context.INITIAL_CONTEXT_FACTORY);
  667                   throw ne;
  668               }
  669   
  670               try {
  671                   factory = (InitialContextFactory)
  672                       helper.loadClass(className).newInstance();
  673               } catch(Exception e) {
  674                   NoInitialContextException ne =
  675                       new NoInitialContextException(
  676                           "Cannot instantiate class: " + className);
  677                   ne.setRootCause(e);
  678                   throw ne;
  679               }
  680           } else {
  681               factory = builder.createInitialContextFactory(env);
  682           }
  683   
  684           return factory.getInitialContext(env);
  685       }
  686   
  687   
  688       /**
  689        * Sets the InitialContextFactory builder to be builder.
  690        *
  691        *<p>
  692        * The builder can only be installed if the executing thread is allowed by
  693        * the security manager to do so. Once installed, the builder cannot
  694        * be replaced.
  695        * @param builder The initial context factory builder to install. If null,
  696        *                no builder is set.
  697        * @exception SecurityException builder cannot be installed for security
  698        *                  reasons.
  699        * @exception NamingException builder cannot be installed for
  700        *         a non-security-related reason.
  701        * @exception IllegalStateException If a builder was previous installed.
  702        * @see #hasInitialContextFactoryBuilder
  703        * @see java.lang.SecurityManager#checkSetFactory
  704        */
  705       public static synchronized void setInitialContextFactoryBuilder(
  706           InitialContextFactoryBuilder builder)
  707           throws NamingException {
  708               if (initctx_factory_builder != null)
  709                   throw new IllegalStateException(
  710                       "InitialContextFactoryBuilder already set");
  711   
  712               SecurityManager security = System.getSecurityManager();
  713               if (security != null) {
  714                   security.checkSetFactory();
  715               }
  716               initctx_factory_builder = builder;
  717       }
  718   
  719       /**
  720        * Determines whether an initial context factory builder has
  721        * been set.
  722        * @return true if an initial context factory builder has
  723        *           been set; false otherwise.
  724        * @see #setInitialContextFactoryBuilder
  725        */
  726       public static boolean hasInitialContextFactoryBuilder() {
  727           return (getInitialContextFactoryBuilder() != null);
  728       }
  729   
  730   // -----  Continuation Context Stuff
  731   
  732       /**
  733        * Constant that holds the name of the environment property into
  734        * which <tt>getContinuationContext()</tt> stores the value of its
  735        * <tt>CannotProceedException</tt> parameter.
  736        * This property is inherited by the continuation context, and may
  737        * be used by that context's service provider to inspect the
  738        * fields of the exception.
  739        *<p>
  740        * The value of this constant is "java.naming.spi.CannotProceedException".
  741        *
  742        * @see #getContinuationContext
  743        * @since 1.3
  744        */
  745       public static final String CPE = "java.naming.spi.CannotProceedException";
  746   
  747       /**
  748        * Creates a context in which to continue a context operation.
  749        *<p>
  750        * In performing an operation on a name that spans multiple
  751        * namespaces, a context from one naming system may need to pass
  752        * the operation on to the next naming system.  The context
  753        * implementation does this by first constructing a
  754        * <code>CannotProceedException</code> containing information
  755        * pinpointing how far it has proceeded.  It then obtains a
  756        * continuation context from JNDI by calling
  757        * <code>getContinuationContext</code>.  The context
  758        * implementation should then resume the context operation by
  759        * invoking the same operation on the continuation context, using
  760        * the remainder of the name that has not yet been resolved.
  761        *<p>
  762        * Before making use of the <tt>cpe</tt> parameter, this method
  763        * updates the environment associated with that object by setting
  764        * the value of the property <a href="#CPE"><tt>CPE</tt></a>
  765        * to <tt>cpe</tt>.  This property will be inherited by the
  766        * continuation context, and may be used by that context's
  767        * service provider to inspect the fields of this exception.
  768        *
  769        * @param cpe
  770        *          The non-null exception that triggered this continuation.
  771        * @return A non-null Context object for continuing the operation.
  772        * @exception NamingException If a naming exception occurred.
  773        */
  774       public static Context getContinuationContext(CannotProceedException cpe)
  775               throws NamingException {
  776   
  777           Hashtable env = cpe.getEnvironment();
  778           if (env == null) {
  779               env = new Hashtable(7);
  780           } else {
  781               // Make a (shallow) copy of the environment.
  782               env = (Hashtable) env.clone();
  783           }
  784           env.put(CPE, cpe);
  785   
  786           ContinuationContext cctx = new ContinuationContext(cpe, env);
  787           return cctx.getTargetContext();
  788       }
  789   
  790   // ------------ State Factory Stuff
  791   
  792       /**
  793        * Retrieves the state of an object for binding.
  794        * <p>
  795        * Service providers that implement the <tt>DirContext</tt> interface
  796        * should use <tt>DirectoryManager.getStateToBind()</tt>, not this method.
  797        * Service providers that implement only the <tt>Context</tt> interface
  798        * should use this method.
  799        *<p>
  800        * This method uses the specified state factories in
  801        * the <tt>Context.STATE_FACTORIES</tt> property from the environment
  802        * properties, and from the provider resource file associated with
  803        * <tt>nameCtx</tt>, in that order.
  804        *    The value of this property is a colon-separated list of factory
  805        *    class names that are tried in order, and the first one that succeeds
  806        *    in returning the object's state is the one used.
  807        * If no object's state can be retrieved in this way, return the
  808        * object itself.
  809        *    If an exception is encountered while retrieving the state, the
  810        *    exception is passed up to the caller.
  811        * <p>
  812        * Note that a state factory
  813        * (an object that implements the StateFactory
  814        * interface) must be public and must have a public constructor that
  815        * accepts no arguments.
  816        * <p>
  817        * The <code>name</code> and <code>nameCtx</code> parameters may
  818        * optionally be used to specify the name of the object being created.
  819        * See the description of "Name and Context Parameters" in
  820        * {@link ObjectFactory#getObjectInstance
  821        *          ObjectFactory.getObjectInstance()}
  822        * for details.
  823        * <p>
  824        * This method may return a <tt>Referenceable</tt> object.  The
  825        * service provider obtaining this object may choose to store it
  826        * directly, or to extract its reference (using
  827        * <tt>Referenceable.getReference()</tt>) and store that instead.
  828        *
  829        * @param obj The non-null object for which to get state to bind.
  830        * @param name The name of this object relative to <code>nameCtx</code>,
  831        *          or null if no name is specified.
  832        * @param nameCtx The context relative to which the <code>name</code>
  833        *          parameter is specified, or null if <code>name</code> is
  834        *          relative to the default initial context.
  835        *  @param environment The possibly null environment to
  836        *          be used in the creation of the state factory and
  837        *  the object's state.
  838        * @return The non-null object representing <tt>obj</tt>'s state for
  839        *  binding.  It could be the object (<tt>obj</tt>) itself.
  840        * @exception NamingException If one of the factories accessed throws an
  841        *          exception, or if an error was encountered while loading
  842        *          and instantiating the factory and object classes.
  843        *          A factory should only throw an exception if it does not want
  844        *          other factories to be used in an attempt to create an object.
  845        *  See <tt>StateFactory.getStateToBind()</tt>.
  846        * @see StateFactory
  847        * @see StateFactory#getStateToBind
  848        * @see DirectoryManager#getStateToBind
  849        * @since 1.3
  850        */
  851       public static Object
  852           getStateToBind(Object obj, Name name, Context nameCtx,
  853                          Hashtable<?,?> environment)
  854           throws NamingException
  855       {
  856   
  857           FactoryEnumeration factories = ResourceManager.getFactories(
  858               Context.STATE_FACTORIES, environment, nameCtx);
  859   
  860           if (factories == null) {
  861               return obj;
  862           }
  863   
  864           // Try each factory until one succeeds
  865           StateFactory factory;
  866           Object answer = null;
  867           while (answer == null && factories.hasMore()) {
  868               factory = (StateFactory)factories.next();
  869               answer = factory.getStateToBind(obj, name, nameCtx, environment);
  870           }
  871   
  872           return (answer != null) ? answer : obj;
  873       }
  874   }

Save This Page
Home » openjdk-7 » javax » naming » spi » [javadoc | source]