1. /*
  2. * @(#)DirectoryManager.java 1.8 01/02/09
  3. *
  4. * Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package javax.naming.spi;
  11. import java.util.Hashtable;
  12. import javax.naming.Context;
  13. import javax.naming.Name;
  14. import javax.naming.Reference;
  15. import javax.naming.Referenceable;
  16. import javax.naming.NamingException;
  17. import javax.naming.CannotProceedException;
  18. import javax.naming.directory.DirContext;
  19. import javax.naming.directory.Attributes;
  20. import com.sun.naming.internal.ResourceManager;
  21. import com.sun.naming.internal.FactoryEnumeration;
  22. /**
  23. * This class contains methods for supporting <tt>DirContext</tt>
  24. * implementations.
  25. *<p>
  26. * This class is an extension of <tt>NamingManager</tt>. It contains methods
  27. * for use by service providers for accessing object factories and
  28. * state factories, and for getting continuation contexts for
  29. * supporting federation.
  30. *<p>
  31. * <tt>DirectoryManager</tt> is safe for concurrent access by multiple threads.
  32. *<p>
  33. * Except as otherwise noted,
  34. * a <tt>Name</tt>, <tt>Attributes</tt>, or environment parameter
  35. * passed to any method is owned by the caller.
  36. * The implementation will not modify the object or keep a reference
  37. * to it, although it may keep a reference to a clone or copy.
  38. *
  39. * @author Rosanna Lee
  40. * @author Scott Seligman
  41. * @version 1.8 01/02/09
  42. *
  43. * @see DirObjectFactory
  44. * @see DirStateFactory
  45. * @since 1.3
  46. */
  47. public class DirectoryManager extends NamingManager {
  48. /*
  49. * Disallow anyone from creating one of these.
  50. */
  51. DirectoryManager() {}
  52. /**
  53. * Creates a context in which to continue a <tt>DirContext</tt> operation.
  54. * Operates just like <tt>NamingManager.getContinuationContext()</tt>,
  55. * only the continuation context returned is a <tt>DirContext</tt>.
  56. *
  57. * @param cpe
  58. * The non-null exception that triggered this continuation.
  59. * @return A non-null <tt>DirContext</tt> object for continuing the operation.
  60. * @exception NamingException If a naming exception occurred.
  61. *
  62. * @see NamingManager#getContinuationContext(CannotProceedException)
  63. */
  64. public static DirContext getContinuationDirContext(
  65. CannotProceedException cpe) throws NamingException {
  66. Hashtable env = cpe.getEnvironment();
  67. if (env == null) {
  68. env = new Hashtable(7);
  69. cpe.setEnvironment(env);
  70. }
  71. env.put(CPE, cpe);
  72. return (new ContinuationDirContext(cpe));
  73. }
  74. /**
  75. * Creates an instance of an object for the specified object,
  76. * attributes, and environment.
  77. * <p>
  78. * This method is the same as <tt>NamingManager.getObjectInstance</tt>
  79. * except for the following differences:
  80. *<ul>
  81. *<li>
  82. * It accepts an <tt>Attributes</tt> parameter that contains attributes
  83. * associated with the object. The <tt>DirObjectFactory</tt> might use these
  84. * attributes to save having to look them up from the directory.
  85. *<li>
  86. * The object factories tried must implement either
  87. * <tt>ObjectFactory</tt> or <tt>DirObjectFactory</tt>.
  88. * If it implements <tt>DirObjectFactory</tt>,
  89. * <tt>DirObjectFactory.getObjectInstance()</tt> is used, otherwise,
  90. * <tt>ObjectFactory.getObjectInstance()</tt> is used.
  91. *</ul>
  92. * Service providers that implement the <tt>DirContext</tt> interface
  93. * should use this method, not <tt>NamingManager.getObjectInstance()</tt>.
  94. *<p>
  95. *
  96. * @param refInfo The possibly null object for which to create an object.
  97. * @param name The name of this object relative to <code>nameCtx</code>.
  98. * Specifying a name is optional; if it is
  99. * omitted, <code>name</code> should be null.
  100. * @param nameCtx The context relative to which the <code>name</code>
  101. * parameter is specified. If null, <code>name</code> is
  102. * relative to the default initial context.
  103. * @param environment The possibly null environment to
  104. * be used in the creation of the object factory and the object.
  105. * @param attrs The possibly null attributes associated with refInfo.
  106. * This might not be the complete set of attributes for refInfo;
  107. * you might be able to read more attributes from the directory.
  108. * @return An object created using <code>refInfo</code> and <tt>attrs</tt> or
  109. * <code>refInfo</code> if an object cannot be created by
  110. * a factory.
  111. * @exception NamingException If a naming exception was encountered
  112. * while attempting to get a URL context, or if one of the
  113. * factories accessed throws a NamingException.
  114. * @exception Exception If one of the factories accessed throws an
  115. * exception, or if an error was encountered while loading
  116. * and instantiating the factory and object classes.
  117. * A factory should only throw an exception if it does not want
  118. * other factories to be used in an attempt to create an object.
  119. * See <tt>DirObjectFactory.getObjectInstance()</tt>.
  120. * @see NamingManager#getURLContext
  121. * @see DirObjectFactory
  122. * @see DirObjectFactory#getObjectInstance
  123. * @since 1.3
  124. */
  125. public static Object getObjectInstance(Object refInfo,
  126. Name name, Context nameCtx, Hashtable environment, Attributes attrs)
  127. throws Exception {
  128. ObjectFactory factory;
  129. ObjectFactoryBuilder builder = getObjectFactoryBuilder();
  130. if (builder != null) {
  131. // builder must return non-null factory
  132. factory = builder.createObjectFactory(refInfo, environment);
  133. if (factory instanceof DirObjectFactory) {
  134. return ((DirObjectFactory)factory).getObjectInstance(
  135. refInfo, name, nameCtx, environment, attrs);
  136. } else {
  137. return factory.getObjectInstance(refInfo, name, nameCtx,
  138. environment);
  139. }
  140. }
  141. // use reference if possible
  142. Reference ref = null;
  143. if (refInfo instanceof Reference) {
  144. ref = (Reference) refInfo;
  145. } else if (refInfo instanceof Referenceable) {
  146. ref = ((Referenceable)(refInfo)).getReference();
  147. }
  148. Object answer;
  149. if (ref != null) {
  150. String f = ref.getFactoryClassName();
  151. if (f != null) {
  152. // if reference identifies a factory, use exclusively
  153. factory = getObjectFactoryFromReference(ref, f);
  154. if (factory instanceof DirObjectFactory) {
  155. return ((DirObjectFactory)factory).getObjectInstance(
  156. ref, name, nameCtx, environment, attrs);
  157. } else if (factory != null) {
  158. return factory.getObjectInstance(ref, name, nameCtx,
  159. environment);
  160. }
  161. // No factory found, so return original refInfo.
  162. // Will reach this point if factory class is not in
  163. // class path and reference does not contain a URL for it
  164. return refInfo;
  165. } else {
  166. // if reference has no factory, check for addresses
  167. // containing URLs
  168. // ignore name & attrs params; not used in URL factory
  169. answer = processURLAddrs(ref, name, nameCtx, environment);
  170. if (answer != null) {
  171. return answer;
  172. }
  173. }
  174. }
  175. // try using any specified factories
  176. answer = createObjectFromFactories(refInfo, name, nameCtx,
  177. environment, attrs);
  178. return (answer != null) ? answer : refInfo;
  179. }
  180. private static Object createObjectFromFactories(Object obj, Name name,
  181. Context nameCtx, Hashtable environment, Attributes attrs)
  182. throws Exception {
  183. FactoryEnumeration factories = ResourceManager.getFactories(
  184. Context.OBJECT_FACTORIES, environment, nameCtx);
  185. if (factories == null)
  186. return null;
  187. ObjectFactory factory;
  188. Object answer = null;
  189. // Try each factory until one succeeds
  190. while (answer == null && factories.hasMore()) {
  191. factory = (ObjectFactory)factories.next();
  192. if (factory instanceof DirObjectFactory) {
  193. answer = ((DirObjectFactory)factory).
  194. getObjectInstance(obj, name, nameCtx, environment, attrs);
  195. } else {
  196. answer =
  197. factory.getObjectInstance(obj, name, nameCtx, environment);
  198. }
  199. }
  200. return answer;
  201. }
  202. /**
  203. * Retrieves the state of an object for binding when given the original
  204. * object and its attributes.
  205. * <p>
  206. * This method is like <tt>NamingManager.getStateToBind</tt> except
  207. * for the following differences:
  208. *<ul>
  209. *<li>It accepts an <tt>Attributes</tt> parameter containing attributes
  210. * that were passed to the <tt>DirContext.bind()</tt> method.
  211. *<li>It returns a non-null <tt>DirStateFactory.Result</tt> instance
  212. * containing the object to be bound, and the attributes to
  213. * accompany the binding. Either the object or the attributes may be null.
  214. *<li>
  215. * The state factories tried must each implement either
  216. * <tt>StateFactory</tt> or <tt>DirStateFactory</tt>.
  217. * If it implements <tt>DirStateFactory</tt>, then
  218. * <tt>DirStateFactory.getStateToBind()</tt> is called; otherwise,
  219. * <tt>StateFactory.getStateToBind()</tt> is called.
  220. *</ul>
  221. *
  222. * Service providers that implement the <tt>DirContext</tt> interface
  223. * should use this method, not <tt>NamingManager.getStateToBind()</tt>.
  224. *<p>
  225. * See NamingManager.getStateToBind() for a description of how
  226. * the list of state factories to be tried is determined.
  227. *<p>
  228. * The object returned by this method is owned by the caller.
  229. * The implementation will not subsequently modify it.
  230. * It will contain either a new <tt>Attributes</tt> object that is
  231. * likewise owned by the caller, or a reference to the original
  232. * <tt>attrs</tt> parameter.
  233. *
  234. * @param obj The non-null object for which to get state to bind.
  235. * @param name The name of this object relative to <code>nameCtx</code>,
  236. * or null if no name is specified.
  237. * @param nameCtx The context relative to which the <code>name</code>
  238. * parameter is specified, or null if <code>name</code> is
  239. * relative to the default initial context.
  240. * @param environment The possibly null environment to
  241. * be used in the creation of the state factory and
  242. * the object's state.
  243. * @param attrs The possibly null Attributes that is to be bound with the
  244. * object.
  245. * @return A non-null DirStateFactory.Result containing
  246. * the object and attributes to be bound.
  247. * If no state factory returns a non-null answer, the result will contain
  248. * the object (<tt>obj</tt>) itself with the original attributes.
  249. * @exception NamingException If a naming exception was encountered
  250. * while using the factories.
  251. * A factory should only throw an exception if it does not want
  252. * other factories to be used in an attempt to create an object.
  253. * See <tt>DirStateFactory.getStateToBind()</tt>.
  254. * @see DirStateFactory
  255. * @see DirStateFactory#getStateToBind
  256. * @see NamingManager#getStateToBind
  257. * @since 1.3
  258. */
  259. public static DirStateFactory.Result
  260. getStateToBind(Object obj, Name name, Context nameCtx,
  261. Hashtable environment, Attributes attrs)
  262. throws NamingException {
  263. // Get list of state factories
  264. FactoryEnumeration factories = ResourceManager.getFactories(
  265. Context.STATE_FACTORIES, environment, nameCtx);
  266. if (factories == null) {
  267. // no factories to try; just return originals
  268. return new DirStateFactory.Result(obj, attrs);
  269. }
  270. // Try each factory until one succeeds
  271. StateFactory factory;
  272. Object objanswer;
  273. DirStateFactory.Result answer = null;
  274. while (answer == null && factories.hasMore()) {
  275. factory = (StateFactory)factories.next();
  276. if (factory instanceof DirStateFactory) {
  277. answer = ((DirStateFactory)factory).
  278. getStateToBind(obj, name, nameCtx, environment, attrs);
  279. } else {
  280. objanswer =
  281. factory.getStateToBind(obj, name, nameCtx, environment);
  282. if (objanswer != null) {
  283. answer = new DirStateFactory.Result(objanswer, attrs);
  284. }
  285. }
  286. }
  287. return (answer != null) ? answer :
  288. new DirStateFactory.Result(obj, attrs); // nothing new
  289. }
  290. }