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