Path: blob/master/src/java.naming/share/classes/javax/naming/spi/DirectoryManager.java
41159 views
/*1* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.naming.spi;2627import java.util.Hashtable;2829import javax.naming.Context;30import javax.naming.Name;31import javax.naming.Reference;32import javax.naming.Referenceable;33import javax.naming.NamingException;34import javax.naming.CannotProceedException;35import javax.naming.directory.DirContext;36import javax.naming.directory.Attributes;3738import com.sun.naming.internal.ResourceManager;39import com.sun.naming.internal.FactoryEnumeration;404142/**43* This class contains methods for supporting {@code DirContext}44* implementations.45*<p>46* This class is an extension of {@code NamingManager}. It contains methods47* for use by service providers for accessing object factories and48* state factories, and for getting continuation contexts for49* supporting federation.50*<p>51* {@code DirectoryManager} is safe for concurrent access by multiple threads.52*<p>53* Except as otherwise noted,54* a {@code Name}, {@code Attributes}, or environment parameter55* passed to any method is owned by the caller.56* The implementation will not modify the object or keep a reference57* to it, although it may keep a reference to a clone or copy.58*59* @author Rosanna Lee60* @author Scott Seligman61*62* @see DirObjectFactory63* @see DirStateFactory64* @since 1.365*/6667public class DirectoryManager extends NamingManager {6869/*70* Disallow anyone from creating one of these.71*/72DirectoryManager() {}7374/**75* Creates a context in which to continue a {@code DirContext} operation.76* Operates just like {@code NamingManager.getContinuationContext()},77* only the continuation context returned is a {@code DirContext}.78*79* @param cpe80* The non-null exception that triggered this continuation.81* @return A non-null {@code DirContext} object for continuing the operation.82* @throws NamingException If a naming exception occurred.83*84* @see NamingManager#getContinuationContext(CannotProceedException)85*/86@SuppressWarnings("unchecked")87public static DirContext getContinuationDirContext(88CannotProceedException cpe) throws NamingException {8990Hashtable<Object,Object> env = (Hashtable<Object,Object>)cpe.getEnvironment();91if (env == null) {92env = new Hashtable<>(7);93} else {94// Make a (shallow) copy of the environment.95env = (Hashtable<Object,Object>) env.clone();96}97env.put(CPE, cpe);9899return (new ContinuationDirContext(cpe, env));100}101102/**103* Creates an instance of an object for the specified object,104* attributes, and environment.105* <p>106* This method is the same as {@code NamingManager.getObjectInstance}107* except for the following differences:108*<ul>109*<li>110* It accepts an {@code Attributes} parameter that contains attributes111* associated with the object. The {@code DirObjectFactory} might use these112* attributes to save having to look them up from the directory.113*<li>114* The object factories tried must implement either115* {@code ObjectFactory} or {@code DirObjectFactory}.116* If it implements {@code DirObjectFactory},117* {@code DirObjectFactory.getObjectInstance()} is used, otherwise,118* {@code ObjectFactory.getObjectInstance()} is used.119*</ul>120* Service providers that implement the {@code DirContext} interface121* should use this method, not {@code NamingManager.getObjectInstance()}.122*123* @param refInfo The possibly null object for which to create an object.124* @param name The name of this object relative to {@code nameCtx}.125* Specifying a name is optional; if it is126* omitted, {@code name} should be null.127* @param nameCtx The context relative to which the {@code name}128* parameter is specified. If null, {@code name} is129* relative to the default initial context.130* @param environment The possibly null environment to131* be used in the creation of the object factory and the object.132* @param attrs The possibly null attributes associated with refInfo.133* This might not be the complete set of attributes for refInfo;134* you might be able to read more attributes from the directory.135* @return An object created using {@code refInfo} and {@code attrs}; or136* {@code refInfo} if an object cannot be created by137* a factory.138* @throws NamingException If a naming exception was encountered139* while attempting to get a URL context, or if one of the140* factories accessed throws a NamingException.141* @throws Exception If one of the factories accessed throws an142* exception, or if an error was encountered while loading143* and instantiating the factory and object classes.144* A factory should only throw an exception if it does not want145* other factories to be used in an attempt to create an object.146* See {@code DirObjectFactory.getObjectInstance()}.147* @see NamingManager#getURLContext148* @see DirObjectFactory149* @see DirObjectFactory#getObjectInstance150* @since 1.3151*/152public static Object153getObjectInstance(Object refInfo, Name name, Context nameCtx,154Hashtable<?,?> environment, Attributes attrs)155throws Exception {156157ObjectFactory factory;158159ObjectFactoryBuilder builder = getObjectFactoryBuilder();160if (builder != null) {161// builder must return non-null factory162factory = builder.createObjectFactory(refInfo, environment);163if (factory instanceof DirObjectFactory) {164return ((DirObjectFactory)factory).getObjectInstance(165refInfo, name, nameCtx, environment, attrs);166} else {167return factory.getObjectInstance(refInfo, name, nameCtx,168environment);169}170}171172// use reference if possible173Reference ref = null;174if (refInfo instanceof Reference) {175ref = (Reference) refInfo;176} else if (refInfo instanceof Referenceable) {177ref = ((Referenceable)(refInfo)).getReference();178}179180Object answer;181182if (ref != null) {183String f = ref.getFactoryClassName();184if (f != null) {185// if reference identifies a factory, use exclusively186187factory = getObjectFactoryFromReference(ref, f);188if (factory instanceof DirObjectFactory) {189return ((DirObjectFactory)factory).getObjectInstance(190ref, name, nameCtx, environment, attrs);191} else if (factory != null) {192return factory.getObjectInstance(ref, name, nameCtx,193environment);194}195// No factory found, so return original refInfo.196// Will reach this point if factory class is not in197// class path and reference does not contain a URL for it198return refInfo;199200} else {201// if reference has no factory, check for addresses202// containing URLs203// ignore name & attrs params; not used in URL factory204205answer = processURLAddrs(ref, name, nameCtx, environment);206if (answer != null) {207return answer;208}209}210}211212// try using any specified factories213answer = createObjectFromFactories(refInfo, name, nameCtx,214environment, attrs);215return (answer != null) ? answer : refInfo;216}217218private static Object createObjectFromFactories(Object obj, Name name,219Context nameCtx, Hashtable<?,?> environment, Attributes attrs)220throws Exception {221222FactoryEnumeration factories = ResourceManager.getFactories(223Context.OBJECT_FACTORIES, environment, nameCtx);224225if (factories == null)226return null;227228ObjectFactory factory;229Object answer = null;230// Try each factory until one succeeds231while (answer == null && factories.hasMore()) {232factory = (ObjectFactory)factories.next();233if (factory instanceof DirObjectFactory) {234answer = ((DirObjectFactory)factory).235getObjectInstance(obj, name, nameCtx, environment, attrs);236} else {237answer =238factory.getObjectInstance(obj, name, nameCtx, environment);239}240}241return answer;242}243244/**245* Retrieves the state of an object for binding when given the original246* object and its attributes.247* <p>248* This method is like {@code NamingManager.getStateToBind} except249* for the following differences:250*<ul>251*<li>It accepts an {@code Attributes} parameter containing attributes252* that were passed to the {@code DirContext.bind()} method.253*<li>It returns a non-null {@code DirStateFactory.Result} instance254* containing the object to be bound, and the attributes to255* accompany the binding. Either the object or the attributes may be null.256*<li>257* The state factories tried must each implement either258* {@code StateFactory} or {@code DirStateFactory}.259* If it implements {@code DirStateFactory}, then260* {@code DirStateFactory.getStateToBind()} is called; otherwise,261* {@code StateFactory.getStateToBind()} is called.262*</ul>263*264* Service providers that implement the {@code DirContext} interface265* should use this method, not {@code NamingManager.getStateToBind()}.266*<p>267* See NamingManager.getStateToBind() for a description of how268* the list of state factories to be tried is determined.269*<p>270* The object returned by this method is owned by the caller.271* The implementation will not subsequently modify it.272* It will contain either a new {@code Attributes} object that is273* likewise owned by the caller, or a reference to the original274* {@code attrs} parameter.275*276* @param obj The non-null object for which to get state to bind.277* @param name The name of this object relative to {@code nameCtx},278* or null if no name is specified.279* @param nameCtx The context relative to which the {@code name}280* parameter is specified, or null if {@code name} is281* relative to the default initial context.282* @param environment The possibly null environment to283* be used in the creation of the state factory and284* the object's state.285* @param attrs The possibly null Attributes that is to be bound with the286* object.287* @return A non-null DirStateFactory.Result containing288* the object and attributes to be bound.289* If no state factory returns a non-null answer, the result will contain290* the object ({@code obj}) itself with the original attributes.291* @throws NamingException If a naming exception was encountered292* while using the factories.293* A factory should only throw an exception if it does not want294* other factories to be used in an attempt to create an object.295* See {@code DirStateFactory.getStateToBind()}.296* @see DirStateFactory297* @see DirStateFactory#getStateToBind298* @see NamingManager#getStateToBind299* @since 1.3300*/301public static DirStateFactory.Result302getStateToBind(Object obj, Name name, Context nameCtx,303Hashtable<?,?> environment, Attributes attrs)304throws NamingException {305306// Get list of state factories307FactoryEnumeration factories = ResourceManager.getFactories(308Context.STATE_FACTORIES, environment, nameCtx);309310if (factories == null) {311// no factories to try; just return originals312return new DirStateFactory.Result(obj, attrs);313}314315// Try each factory until one succeeds316StateFactory factory;317Object objanswer;318DirStateFactory.Result answer = null;319while (answer == null && factories.hasMore()) {320factory = (StateFactory)factories.next();321if (factory instanceof DirStateFactory) {322answer = ((DirStateFactory)factory).323getStateToBind(obj, name, nameCtx, environment, attrs);324} else {325objanswer =326factory.getStateToBind(obj, name, nameCtx, environment);327if (objanswer != null) {328answer = new DirStateFactory.Result(objanswer, attrs);329}330}331}332333return (answer != null) ? answer :334new DirStateFactory.Result(obj, attrs); // nothing new335}336}337338339