< prev index next >

src/java.naming/share/classes/javax/naming/spi/NamingManager.java

Print this page


   1 /*
   2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.naming.spi;
  27 
  28 import java.net.MalformedURLException;


  29 import java.util.*;
  30 
  31 
  32 import javax.naming.*;
  33 import com.sun.naming.internal.VersionHelper;
  34 import com.sun.naming.internal.ResourceManager;
  35 import com.sun.naming.internal.FactoryEnumeration;

  36 
  37 /**
  38  * This class contains methods for creating context objects
  39  * and objects referred to by location information in the naming
  40  * or directory service.
  41  *<p>
  42  * This class cannot be instantiated.  It has only static methods.
  43  *<p>
  44  * The mention of URL in the documentation for this class refers to
  45  * a URL string as defined by RFC 1738 and its related RFCs. It is
  46  * any string that conforms to the syntax described therein, and
  47  * may not always have corresponding support in the java.net.URL
  48  * class or Web browsers.
  49  *<p>
  50  * NamingManager is safe for concurrent access by multiple threads.
  51  *<p>
  52  * Except as otherwise noted,
  53  * a {@code Name} or environment parameter
  54  * passed to any method is owned by the caller.
  55  * The implementation will not modify the object or keep a reference


  62 
  63 public class NamingManager {
  64 
  65     /*
  66      * Disallow anyone from creating one of these.
  67      * Made package private so that DirectoryManager can subclass.
  68      */
  69 
  70     NamingManager() {}
  71 
  72     // should be protected and package private
  73     static final VersionHelper helper = VersionHelper.getVersionHelper();
  74 
  75 // --------- object factory stuff
  76 
  77     /**
  78      * Package-private; used by DirectoryManager and NamingManager.
  79      */
  80     private static ObjectFactoryBuilder object_factory_builder = null;
  81 



  82     /**
  83      * The ObjectFactoryBuilder determines the policy used when
  84      * trying to load object factories.
  85      * See getObjectInstance() and class ObjectFactory for a description
  86      * of the default policy.
  87      * setObjectFactoryBuilder() overrides this default policy by installing
  88      * an ObjectFactoryBuilder. Subsequent object factories will
  89      * be loaded and created using the installed builder.
  90      *<p>
  91      * The builder can only be installed if the executing thread is allowed
  92      * (by the security manager's checkSetFactory() method) to do so.
  93      * Once installed, the builder cannot be replaced.
  94      *
  95      * @param builder The factory builder to install. If null, no builder
  96      *                  is installed.
  97      * @exception SecurityException builder cannot be installed
  98      *          for security reasons.
  99      * @exception NamingException builder cannot be installed for
 100      *         a non-security-related reason.
 101      * @exception IllegalStateException If a factory has already been installed.


 655      *         be in a package which is exported by that module to the
 656      *         {@code java.naming} module.)</li>
 657      *     </ul>
 658      * </li>
 659      * </ul>
 660      * @param env The possibly null environment properties used when
 661      *                  creating the context.
 662      * @return A non-null initial context.
 663      * @exception NoInitialContextException If the
 664      *          {@code Context.INITIAL_CONTEXT_FACTORY} property
 665      *         is not found or names a nonexistent
 666      *         class or a class that cannot be instantiated,
 667      *          or if the initial context could not be created for some other
 668      *          reason.
 669      * @exception NamingException If some other naming exception was encountered.
 670      * @see javax.naming.InitialContext
 671      * @see javax.naming.directory.InitialDirContext
 672      */
 673     public static Context getInitialContext(Hashtable<?,?> env)
 674         throws NamingException {

 675         InitialContextFactory factory = null;
 676 
 677         InitialContextFactoryBuilder builder = getInitialContextFactoryBuilder();
 678         if (builder == null) {
 679             // No builder installed, use property
 680             // Get initial context factory class name
 681 
 682             String className = env != null ?
 683                 (String)env.get(Context.INITIAL_CONTEXT_FACTORY) : null;
 684             if (className == null) {
 685                 NoInitialContextException ne = new NoInitialContextException(
 686                     "Need to specify class name in environment or system " +
 687                     "property, or in an application resource file: " +
 688                     Context.INITIAL_CONTEXT_FACTORY);
 689                 throw ne;
 690             }
 691 
 692             ServiceLoader<InitialContextFactory> loader =
 693                     ServiceLoader.load(InitialContextFactory.class);








 694 
 695             Iterator<InitialContextFactory> iterator = loader.iterator();
 696             try {
 697                 while (iterator.hasNext()) {
 698                     InitialContextFactory f = iterator.next();
 699                     if (f.getClass().getName().equals(className)) {
 700                         factory = f;
 701                         break;
 702                     }


 703                 }
















 704             } catch (ServiceConfigurationError e) {
 705                 NoInitialContextException ne =
 706                         new NoInitialContextException(
 707                                 "Cannot load initial context factory "
 708                                         + "'" + className + "'");
 709                 ne.setRootCause(e);
 710                 throw ne;
 711             }
 712 
 713             if (factory == null) {
 714                 try {
 715                     @SuppressWarnings("deprecation")
 716                     Object o = helper.loadClass(className).newInstance();
 717                     factory = (InitialContextFactory) o;
 718                 } catch (Exception e) {
 719                     NoInitialContextException ne =
 720                             new NoInitialContextException(
 721                                     "Cannot instantiate class: " + className);
 722                     ne.setRootCause(e);
 723                     throw ne;
 724                 }
 725             }
 726         } else {
 727             factory = builder.createInitialContextFactory(env);
 728         }
 729 
 730         return factory.getInitialContext(env);
 731     }
 732 
 733 
 734     /**
 735      * Sets the InitialContextFactory builder to be builder.
 736      *
 737      *<p>
 738      * The builder can only be installed if the executing thread is allowed by
 739      * the security manager to do so. Once installed, the builder cannot
 740      * be replaced.
 741      * @param builder The initial context factory builder to install. If null,
 742      *                no builder is set.
 743      * @exception SecurityException builder cannot be installed for security
 744      *                  reasons.
 745      * @exception NamingException builder cannot be installed for
 746      *         a non-security-related reason.
 747      * @exception IllegalStateException If a builder was previous installed.
 748      * @see #hasInitialContextFactoryBuilder
 749      * @see java.lang.SecurityManager#checkSetFactory
 750      */


 903                        Hashtable<?,?> environment)
 904         throws NamingException
 905     {
 906 
 907         FactoryEnumeration factories = ResourceManager.getFactories(
 908             Context.STATE_FACTORIES, environment, nameCtx);
 909 
 910         if (factories == null) {
 911             return obj;
 912         }
 913 
 914         // Try each factory until one succeeds
 915         StateFactory factory;
 916         Object answer = null;
 917         while (answer == null && factories.hasMore()) {
 918             factory = (StateFactory)factories.next();
 919             answer = factory.getStateToBind(obj, name, nameCtx, environment);
 920         }
 921 
 922         return (answer != null) ? answer : obj;














 923     }
 924 }
   1 /*
   2  * Copyright (c) 1999, 2020, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.naming.spi;
  27 
  28 import java.net.MalformedURLException;
  29 import java.security.AccessController;
  30 import java.security.PrivilegedAction;
  31 import java.util.*;
  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 import jdk.internal.loader.ClassLoaderValue;
  38 
  39 /**
  40  * This class contains methods for creating context objects
  41  * and objects referred to by location information in the naming
  42  * or directory service.
  43  *<p>
  44  * This class cannot be instantiated.  It has only static methods.
  45  *<p>
  46  * The mention of URL in the documentation for this class refers to
  47  * a URL string as defined by RFC 1738 and its related RFCs. It is
  48  * any string that conforms to the syntax described therein, and
  49  * may not always have corresponding support in the java.net.URL
  50  * class or Web browsers.
  51  *<p>
  52  * NamingManager is safe for concurrent access by multiple threads.
  53  *<p>
  54  * Except as otherwise noted,
  55  * a {@code Name} or environment parameter
  56  * passed to any method is owned by the caller.
  57  * The implementation will not modify the object or keep a reference


  64 
  65 public class NamingManager {
  66 
  67     /*
  68      * Disallow anyone from creating one of these.
  69      * Made package private so that DirectoryManager can subclass.
  70      */
  71 
  72     NamingManager() {}
  73 
  74     // should be protected and package private
  75     static final VersionHelper helper = VersionHelper.getVersionHelper();
  76 
  77 // --------- object factory stuff
  78 
  79     /**
  80      * Package-private; used by DirectoryManager and NamingManager.
  81      */
  82     private static ObjectFactoryBuilder object_factory_builder = null;
  83 
  84     private static final ClassLoaderValue<InitialContextFactory> FACTORIES_CACHE =
  85             new ClassLoaderValue<>();
  86 
  87     /**
  88      * The ObjectFactoryBuilder determines the policy used when
  89      * trying to load object factories.
  90      * See getObjectInstance() and class ObjectFactory for a description
  91      * of the default policy.
  92      * setObjectFactoryBuilder() overrides this default policy by installing
  93      * an ObjectFactoryBuilder. Subsequent object factories will
  94      * be loaded and created using the installed builder.
  95      *<p>
  96      * The builder can only be installed if the executing thread is allowed
  97      * (by the security manager's checkSetFactory() method) to do so.
  98      * Once installed, the builder cannot be replaced.
  99      *
 100      * @param builder The factory builder to install. If null, no builder
 101      *                  is installed.
 102      * @exception SecurityException builder cannot be installed
 103      *          for security reasons.
 104      * @exception NamingException builder cannot be installed for
 105      *         a non-security-related reason.
 106      * @exception IllegalStateException If a factory has already been installed.


 660      *         be in a package which is exported by that module to the
 661      *         {@code java.naming} module.)</li>
 662      *     </ul>
 663      * </li>
 664      * </ul>
 665      * @param env The possibly null environment properties used when
 666      *                  creating the context.
 667      * @return A non-null initial context.
 668      * @exception NoInitialContextException If the
 669      *          {@code Context.INITIAL_CONTEXT_FACTORY} property
 670      *         is not found or names a nonexistent
 671      *         class or a class that cannot be instantiated,
 672      *          or if the initial context could not be created for some other
 673      *          reason.
 674      * @exception NamingException If some other naming exception was encountered.
 675      * @see javax.naming.InitialContext
 676      * @see javax.naming.directory.InitialDirContext
 677      */
 678     public static Context getInitialContext(Hashtable<?,?> env)
 679         throws NamingException {
 680         ClassLoader loader;
 681         InitialContextFactory factory = null;
 682 
 683         InitialContextFactoryBuilder builder = getInitialContextFactoryBuilder();
 684         if (builder == null) {
 685             // No builder installed, use property
 686             // Get initial context factory class name
 687 
 688             String className = env != null ?
 689                 (String)env.get(Context.INITIAL_CONTEXT_FACTORY) : null;
 690             if (className == null) {
 691                 NoInitialContextException ne = new NoInitialContextException(
 692                     "Need to specify class name in environment or system " +
 693                     "property, or in an application resource file: " +
 694                     Context.INITIAL_CONTEXT_FACTORY);
 695                 throw ne;
 696             }
 697 
 698             if (System.getSecurityManager() == null) {
 699                 loader = Thread.currentThread().getContextClassLoader();
 700                 if (loader == null) loader = ClassLoader.getSystemClassLoader();
 701             } else {
 702                 PrivilegedAction<ClassLoader> pa = () -> {
 703                     ClassLoader cl = Thread.currentThread().getContextClassLoader();
 704                     return (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
 705                 };
 706                 loader = AccessController.doPrivileged(pa);
 707             }
 708 
 709             var key = FACTORIES_CACHE.sub(className);
 710             try {
 711                 factory = key.computeIfAbsent(loader, (ld, ky) -> getFactory(ky.key()));
 712             } catch (FactoryInitializationError e) {
 713                 throw e.getCause();


 714             }
 715         } else {
 716             factory = builder.createInitialContextFactory(env);
 717         }
 718 
 719         return factory.getInitialContext(env);
 720     }
 721 
 722     private static InitialContextFactory getFactory(String className) {
 723         InitialContextFactory factory;
 724         try {
 725             ServiceLoader<InitialContextFactory> loader =
 726                     ServiceLoader.load(InitialContextFactory.class);
 727 
 728             factory = loader
 729                     .stream()
 730                     .filter(p -> p.type().getName().equals(className))
 731                     .findFirst()
 732                     .map(ServiceLoader.Provider::get)
 733                     .orElse(null);
 734         } catch (ServiceConfigurationError e) {
 735             NoInitialContextException ne =
 736                     new NoInitialContextException(
 737                             "Cannot load initial context factory "
 738                                     + "'" + className + "'");
 739             ne.setRootCause(e);
 740             throw new FactoryInitializationError(ne);
 741         }
 742 
 743         if (factory == null) {
 744             try {
 745                 @SuppressWarnings("deprecation")
 746                 Object o = helper.loadClass(className).newInstance();
 747                 factory = (InitialContextFactory) o;
 748             } catch (Exception e) {
 749                 NoInitialContextException ne =
 750                         new NoInitialContextException(
 751                                 "Cannot instantiate class: " + className);
 752                 ne.setRootCause(e);
 753                 throw new FactoryInitializationError(ne);
 754             }
 755         }
 756         return factory;




 757     }
 758 
 759 
 760     /**
 761      * Sets the InitialContextFactory builder to be builder.
 762      *
 763      *<p>
 764      * The builder can only be installed if the executing thread is allowed by
 765      * the security manager to do so. Once installed, the builder cannot
 766      * be replaced.
 767      * @param builder The initial context factory builder to install. If null,
 768      *                no builder is set.
 769      * @exception SecurityException builder cannot be installed for security
 770      *                  reasons.
 771      * @exception NamingException builder cannot be installed for
 772      *         a non-security-related reason.
 773      * @exception IllegalStateException If a builder was previous installed.
 774      * @see #hasInitialContextFactoryBuilder
 775      * @see java.lang.SecurityManager#checkSetFactory
 776      */


 929                        Hashtable<?,?> environment)
 930         throws NamingException
 931     {
 932 
 933         FactoryEnumeration factories = ResourceManager.getFactories(
 934             Context.STATE_FACTORIES, environment, nameCtx);
 935 
 936         if (factories == null) {
 937             return obj;
 938         }
 939 
 940         // Try each factory until one succeeds
 941         StateFactory factory;
 942         Object answer = null;
 943         while (answer == null && factories.hasMore()) {
 944             factory = (StateFactory)factories.next();
 945             answer = factory.getStateToBind(obj, name, nameCtx, environment);
 946         }
 947 
 948         return (answer != null) ? answer : obj;
 949     }
 950 
 951     private static class FactoryInitializationError extends Error {
 952         @java.io.Serial
 953         static final long serialVersionUID = -5805552256848841560L;
 954 
 955         private FactoryInitializationError(NoInitialContextException cause) {
 956             super(cause);
 957         }
 958 
 959         @Override
 960         public NoInitialContextException getCause() {
 961             return (NoInitialContextException) super.getCause();
 962         }
 963     }
 964 }
< prev index next >