/* * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.naming.spi; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.Reference; import javax.naming.Referenceable; import javax.naming.NamingException; import javax.naming.CannotProceedException; import javax.naming.directory.DirContext; import javax.naming.directory.Attributes; import com.sun.naming.internal.ResourceManager; import com.sun.naming.internal.FactoryEnumeration; /** * This class contains methods for supporting DirContext * implementations. *

* This class is an extension of NamingManager. It contains methods * for use by service providers for accessing object factories and * state factories, and for getting continuation contexts for * supporting federation. *

* DirectoryManager is safe for concurrent access by multiple threads. *

* Except as otherwise noted, * a Name, Attributes, or environment parameter * passed to any method is owned by the caller. * The implementation will not modify the object or keep a reference * to it, although it may keep a reference to a clone or copy. * * @author Rosanna Lee * @author Scott Seligman * * @see DirObjectFactory * @see DirStateFactory * @since 1.3 */ public class DirectoryManager extends NamingManager { /* * Disallow anyone from creating one of these. */ DirectoryManager() {} /** * Creates a context in which to continue a DirContext operation. * Operates just like NamingManager.getContinuationContext(), * only the continuation context returned is a DirContext. * * @param cpe * The non-null exception that triggered this continuation. * @return A non-null DirContext object for continuing the operation. * @exception NamingException If a naming exception occurred. * * @see NamingManager#getContinuationContext(CannotProceedException) */ @SuppressWarnings("unchecked") public static DirContext getContinuationDirContext( CannotProceedException cpe) throws NamingException { Hashtable env = (Hashtable)cpe.getEnvironment(); if (env == null) { env = new Hashtable<>(7); } else { // Make a (shallow) copy of the environment. env = (Hashtable) env.clone(); } env.put(CPE, cpe); return (new ContinuationDirContext(cpe, env)); } /** * Creates an instance of an object for the specified object, * attributes, and environment. *

* This method is the same as NamingManager.getObjectInstance * except for the following differences: *

* Service providers that implement the DirContext interface * should use this method, not NamingManager.getObjectInstance(). * * @param refInfo The possibly null object for which to create an object. * @param name The name of this object relative to nameCtx. * Specifying a name is optional; if it is * omitted, name should be null. * @param nameCtx The context relative to which the name * parameter is specified. If null, name is * relative to the default initial context. * @param environment The possibly null environment to * be used in the creation of the object factory and the object. * @param attrs The possibly null attributes associated with refInfo. * This might not be the complete set of attributes for refInfo; * you might be able to read more attributes from the directory. * @return An object created using refInfo and attrs; or * refInfo if an object cannot be created by * a factory. * @exception NamingException If a naming exception was encountered * while attempting to get a URL context, or if one of the * factories accessed throws a NamingException. * @exception Exception If one of the factories accessed throws an * exception, or if an error was encountered while loading * and instantiating the factory and object classes. * A factory should only throw an exception if it does not want * other factories to be used in an attempt to create an object. * See DirObjectFactory.getObjectInstance(). * @see NamingManager#getURLContext * @see DirObjectFactory * @see DirObjectFactory#getObjectInstance * @since 1.3 */ public static Object getObjectInstance(Object refInfo, Name name, Context nameCtx, Hashtable environment, Attributes attrs) throws Exception { ObjectFactory factory; ObjectFactoryBuilder builder = getObjectFactoryBuilder(); if (builder != null) { // builder must return non-null factory factory = builder.createObjectFactory(refInfo, environment); if (factory instanceof DirObjectFactory) { return ((DirObjectFactory)factory).getObjectInstance( refInfo, name, nameCtx, environment, attrs); } else { return factory.getObjectInstance(refInfo, name, nameCtx, environment); } } // use reference if possible Reference ref = null; if (refInfo instanceof Reference) { ref = (Reference) refInfo; } else if (refInfo instanceof Referenceable) { ref = ((Referenceable)(refInfo)).getReference(); } Object answer; if (ref != null) { String f = ref.getFactoryClassName(); if (f != null) { // if reference identifies a factory, use exclusively factory = getObjectFactoryFromReference(ref, f); if (factory instanceof DirObjectFactory) { return ((DirObjectFactory)factory).getObjectInstance( ref, name, nameCtx, environment, attrs); } else if (factory != null) { return factory.getObjectInstance(ref, name, nameCtx, environment); } // No factory found, so return original refInfo. // Will reach this point if factory class is not in // class path and reference does not contain a URL for it return refInfo; } else { // if reference has no factory, check for addresses // containing URLs // ignore name & attrs params; not used in URL factory answer = processURLAddrs(ref, name, nameCtx, environment); if (answer != null) { return answer; } } } // try using any specified factories answer = createObjectFromFactories(refInfo, name, nameCtx, environment, attrs); return (answer != null) ? answer : refInfo; } private static Object createObjectFromFactories(Object obj, Name name, Context nameCtx, Hashtable environment, Attributes attrs) throws Exception { FactoryEnumeration factories = ResourceManager.getFactories( Context.OBJECT_FACTORIES, environment, nameCtx); if (factories == null) return null; ObjectFactory factory; Object answer = null; // Try each factory until one succeeds while (answer == null && factories.hasMore()) { factory = (ObjectFactory)factories.next(); if (factory instanceof DirObjectFactory) { answer = ((DirObjectFactory)factory). getObjectInstance(obj, name, nameCtx, environment, attrs); } else { answer = factory.getObjectInstance(obj, name, nameCtx, environment); } } return answer; } /** * Retrieves the state of an object for binding when given the original * object and its attributes. *

* This method is like NamingManager.getStateToBind except * for the following differences: *

* * Service providers that implement the DirContext interface * should use this method, not NamingManager.getStateToBind(). *

* See NamingManager.getStateToBind() for a description of how * the list of state factories to be tried is determined. *

* The object returned by this method is owned by the caller. * The implementation will not subsequently modify it. * It will contain either a new Attributes object that is * likewise owned by the caller, or a reference to the original * attrs parameter. * * @param obj The non-null object for which to get state to bind. * @param name The name of this object relative to nameCtx, * or null if no name is specified. * @param nameCtx The context relative to which the name * parameter is specified, or null if name is * relative to the default initial context. * @param environment The possibly null environment to * be used in the creation of the state factory and * the object's state. * @param attrs The possibly null Attributes that is to be bound with the * object. * @return A non-null DirStateFactory.Result containing * the object and attributes to be bound. * If no state factory returns a non-null answer, the result will contain * the object (obj) itself with the original attributes. * @exception NamingException If a naming exception was encountered * while using the factories. * A factory should only throw an exception if it does not want * other factories to be used in an attempt to create an object. * See DirStateFactory.getStateToBind(). * @see DirStateFactory * @see DirStateFactory#getStateToBind * @see NamingManager#getStateToBind * @since 1.3 */ public static DirStateFactory.Result getStateToBind(Object obj, Name name, Context nameCtx, Hashtable environment, Attributes attrs) throws NamingException { // Get list of state factories FactoryEnumeration factories = ResourceManager.getFactories( Context.STATE_FACTORIES, environment, nameCtx); if (factories == null) { // no factories to try; just return originals return new DirStateFactory.Result(obj, attrs); } // Try each factory until one succeeds StateFactory factory; Object objanswer; DirStateFactory.Result answer = null; while (answer == null && factories.hasMore()) { factory = (StateFactory)factories.next(); if (factory instanceof DirStateFactory) { answer = ((DirStateFactory)factory). getStateToBind(obj, name, nameCtx, environment, attrs); } else { objanswer = factory.getStateToBind(obj, name, nameCtx, environment); if (objanswer != null) { answer = new DirStateFactory.Result(objanswer, attrs); } } } return (answer != null) ? answer : new DirStateFactory.Result(obj, attrs); // nothing new } }