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 */
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 */
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 static final long serialVersionUID = -5805552256848841560L;
953
954 private FactoryInitializationError(NoInitialContextException cause) {
955 super(cause);
956 }
957
958 @Override
959 public NoInitialContextException getCause() {
960 return (NoInitialContextException) super.getCause();
961 }
962 }
963 }
|