1. /*
  2. * @(#)ControlFactory.java 1.9 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.naming.ldap;
  8. import javax.naming.NamingException;
  9. import javax.naming.Context;
  10. import java.util.Hashtable;
  11. import com.sun.naming.internal.FactoryEnumeration;
  12. import com.sun.naming.internal.ResourceManager;
  13. /**
  14. * This abstract class represents a factory for creating LDAPv3 controls.
  15. * LDAPv3 controls are defined in
  16. * <A HREF="ftp://ftp.isi.edu/in-notes/rfc2251.txt">RFC 2251</A>.
  17. *<p>
  18. * When a service provider receives a response control, it uses control
  19. * factories to return the specific/appropriate control class implementation.
  20. *
  21. * @author Rosanna Lee
  22. * @author Scott Seligman
  23. * @author Vincent Ryan
  24. * @version 1.9 03/01/23
  25. *
  26. * @see Control
  27. * @since 1.3
  28. */
  29. public abstract class ControlFactory {
  30. /*
  31. * Creates a new instance of a control factory.
  32. */
  33. protected ControlFactory() {
  34. }
  35. /**
  36. * Creates a control using this control factory.
  37. *<p>
  38. * The factory is used by the service provider to return controls
  39. * that it reads from the LDAP protocol as specialized control classes.
  40. * Without this mechanism, the provider would be returning
  41. * controls that only contained data in BER encoded format.
  42. *<p>
  43. * Typically, <tt>ctl</tt> is a "basic" control containing
  44. * BER encoded data. The factory is used to create a specialized
  45. * control implementation, usually by decoding the BER encoded data,
  46. * that provides methods to access that data in a type-safe and friendly
  47. * manner.
  48. * <p>
  49. * For example, a factory might use the BER encoded data in
  50. * basic control and return an instance of a VirtualListReplyControl.
  51. *<p>
  52. * If this factory cannot create a control using the argument supplied,
  53. * it should return null.
  54. * A factory should only throw an exception if it is sure that
  55. * it is the only intended factory and that no other control factories
  56. * should be tried. This might happen, for example, if the BER data
  57. * in the control does not match what is expected of a control with
  58. * the given OID. Since this method throws <tt>NamingException</tt>,
  59. * any other internally generated exception that should be propagated
  60. * must be wrapped inside a <tt>NamingException</tt>.
  61. *
  62. * @param ctl A non-null control.
  63. *
  64. * @return A possibly null Control.
  65. * @exception NamingException If <tt>ctl</tt> contains invalid data that prevents it
  66. * from being used to create a control. A factory should only throw
  67. * an exception if it knows how to produce the control (identified by the OID)
  68. * but is unable to because of, for example invalid BER data.
  69. */
  70. public abstract Control getControlInstance(Control ctl) throws NamingException;
  71. /**
  72. * Creates a control using known control factories.
  73. * <p>
  74. * The following rule is used to create the control:
  75. *<ul>
  76. * <li> Use the control factories specified in
  77. * the <tt>LdapContext.CONTROL_FACTORIES</tt> property of the
  78. * environment, and of the provider resource file associated with
  79. * <tt>ctx</tt>, in that order.
  80. * The value of this property is a colon-separated list of factory
  81. * class names that are tried in order, and the first one that succeeds
  82. * in creating the control is the one used.
  83. * If none of the factories can be loaded,
  84. * return <code>ctl</code>.
  85. * If an exception is encountered while creating the control, the
  86. * exception is passed up to the caller.
  87. *</ul>
  88. * <p>
  89. * Note that a control factory
  90. * must be public and must have a public constructor that accepts no arguments.
  91. * <p>
  92. * @param ctl The non-null control object containing the OID and BER data.
  93. * @param ctx The possibly null context in which the control is being created.
  94. * If null, no such information is available.
  95. * @param env The possibly null environment of the context. This is used
  96. * to find the value of the <tt>LdapContext.CONTROL_FACTORIES</tt> property.
  97. * @return A control object created using <code>ctl</code> or
  98. * <code>ctl</code> if a control object cannot be created using
  99. * the algorithm described above.
  100. * @exception NamingException if a naming exception was encountered
  101. * while attempting to create the control object.
  102. * If one of the factories accessed throws an
  103. * exception, it is propagated up to the caller.
  104. * If an error was encountered while loading
  105. * and instantiating the factory and object classes, the exception
  106. * is wrapped inside a <tt>NamingException</tt> and then rethrown.
  107. */
  108. public static Control getControlInstance(Control ctl, Context ctx,
  109. Hashtable env)
  110. throws NamingException {
  111. // Get object factories list from environment properties or
  112. // provider resource file.
  113. FactoryEnumeration factories = ResourceManager.getFactories(
  114. LdapContext.CONTROL_FACTORIES, env, ctx);
  115. if (factories == null) {
  116. return ctl;
  117. }
  118. // Try each factory until one succeeds
  119. Control answer = null;
  120. ControlFactory factory;
  121. while (answer == null && factories.hasMore()) {
  122. factory = (ControlFactory)factories.next();
  123. answer = factory.getControlInstance(ctl);
  124. }
  125. return (answer != null)? answer : ctl;
  126. }
  127. }