| /* |
| * Copyright (c) 1999, 2004, 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 <tt>DirContext</tt> |
| * implementations. |
| *<p> |
| * This class is an extension of <tt>NamingManager</tt>. It contains methods |
| * for use by service providers for accessing object factories and |
| * state factories, and for getting continuation contexts for |
| * supporting federation. |
| *<p> |
| * <tt>DirectoryManager</tt> is safe for concurrent access by multiple threads. |
| *<p> |
| * Except as otherwise noted, |
| * a <tt>Name</tt>, <tt>Attributes</tt>, 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 <tt>DirContext</tt> operation. |
| * Operates just like <tt>NamingManager.getContinuationContext()</tt>, |
| * only the continuation context returned is a <tt>DirContext</tt>. |
| * |
| * @param cpe |
| * The non-null exception that triggered this continuation. |
| * @return A non-null <tt>DirContext</tt> object for continuing the operation. |
| * @exception NamingException If a naming exception occurred. |
| * |
| * @see NamingManager#getContinuationContext(CannotProceedException) |
| */ |
| public static DirContext getContinuationDirContext( |
| CannotProceedException cpe) throws NamingException { |
| |
| Hashtable env = 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. |
| * <p> |
| * This method is the same as <tt>NamingManager.getObjectInstance</tt> |
| * except for the following differences: |
| *<ul> |
| *<li> |
| * It accepts an <tt>Attributes</tt> parameter that contains attributes |
| * associated with the object. The <tt>DirObjectFactory</tt> might use these |
| * attributes to save having to look them up from the directory. |
| *<li> |
| * The object factories tried must implement either |
| * <tt>ObjectFactory</tt> or <tt>DirObjectFactory</tt>. |
| * If it implements <tt>DirObjectFactory</tt>, |
| * <tt>DirObjectFactory.getObjectInstance()</tt> is used, otherwise, |
| * <tt>ObjectFactory.getObjectInstance()</tt> is used. |
| *</ul> |
| * Service providers that implement the <tt>DirContext</tt> interface |
| * should use this method, not <tt>NamingManager.getObjectInstance()</tt>. |
| *<p> |
| * |
| * @param refInfo The possibly null object for which to create an object. |
| * @param name The name of this object relative to <code>nameCtx</code>. |
| * Specifying a name is optional; if it is |
| * omitted, <code>name</code> should be null. |
| * @param nameCtx The context relative to which the <code>name</code> |
| * parameter is specified. If null, <code>name</code> 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 <code>refInfo</code> and <tt>attrs</tt>; or |
| * <code>refInfo</code> 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 <tt>DirObjectFactory.getObjectInstance()</tt>. |
| * @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. |
| * <p> |
| * This method is like <tt>NamingManager.getStateToBind</tt> except |
| * for the following differences: |
| *<ul> |
| *<li>It accepts an <tt>Attributes</tt> parameter containing attributes |
| * that were passed to the <tt>DirContext.bind()</tt> method. |
| *<li>It returns a non-null <tt>DirStateFactory.Result</tt> instance |
| * containing the object to be bound, and the attributes to |
| * accompany the binding. Either the object or the attributes may be null. |
| *<li> |
| * The state factories tried must each implement either |
| * <tt>StateFactory</tt> or <tt>DirStateFactory</tt>. |
| * If it implements <tt>DirStateFactory</tt>, then |
| * <tt>DirStateFactory.getStateToBind()</tt> is called; otherwise, |
| * <tt>StateFactory.getStateToBind()</tt> is called. |
| *</ul> |
| * |
| * Service providers that implement the <tt>DirContext</tt> interface |
| * should use this method, not <tt>NamingManager.getStateToBind()</tt>. |
| *<p> |
| * See NamingManager.getStateToBind() for a description of how |
| * the list of state factories to be tried is determined. |
| *<p> |
| * The object returned by this method is owned by the caller. |
| * The implementation will not subsequently modify it. |
| * It will contain either a new <tt>Attributes</tt> object that is |
| * likewise owned by the caller, or a reference to the original |
| * <tt>attrs</tt> parameter. |
| * |
| * @param obj The non-null object for which to get state to bind. |
| * @param name The name of this object relative to <code>nameCtx</code>, |
| * or null if no name is specified. |
| * @param nameCtx The context relative to which the <code>name</code> |
| * parameter is specified, or null if <code>name</code> 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 (<tt>obj</tt>) 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 <tt>DirStateFactory.getStateToBind()</tt>. |
| * @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 |
| } |
| } |