View Javadoc
1   /*
2    * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package javax.naming.ldap;
27  
28  import javax.naming.NamingException;
29  import javax.naming.Context;
30  
31  import java.util.Hashtable;
32  
33  import com.sun.naming.internal.FactoryEnumeration;
34  import com.sun.naming.internal.ResourceManager;
35  
36  
37  /**
38    * This abstract class represents a factory for creating LDAPv3 controls.
39    * LDAPv3 controls are defined in
40    * <A HREF="http://www.ietf.org/rfc/rfc2251.txt">RFC 2251</A>.
41    *<p>
42    * When a service provider receives a response control, it uses control
43    * factories to return the specific/appropriate control class implementation.
44    *
45    * @author Rosanna Lee
46    * @author Scott Seligman
47    * @author Vincent Ryan
48    *
49    * @see Control
50    * @since 1.3
51    */
52  
53  public abstract class ControlFactory {
54      /**
55       * Creates a new instance of a control factory.
56       */
57      protected ControlFactory() {
58      }
59  
60      /**
61        * Creates a control using this control factory.
62        *<p>
63        * The factory is used by the service provider to return controls
64        * that it reads from the LDAP protocol as specialized control classes.
65        * Without this mechanism, the provider would be returning
66        * controls that only contained data in BER encoded format.
67        *<p>
68        * Typically, <tt>ctl</tt> is a "basic" control containing
69        * BER encoded data. The factory is used to create a specialized
70        * control implementation, usually by decoding the BER encoded data,
71        * that provides methods to access that data in a type-safe and friendly
72        * manner.
73        * <p>
74        * For example, a factory might use the BER encoded data in
75        * basic control and return an instance of a VirtualListReplyControl.
76        *<p>
77        * If this factory cannot create a control using the argument supplied,
78        * it should return null.
79        * A factory should only throw an exception if it is sure that
80        * it is the only intended factory and that no other control factories
81        * should be tried. This might happen, for example, if the BER data
82        * in the control does not match what is expected of a control with
83        * the given OID. Since this method throws <tt>NamingException</tt>,
84        * any other internally generated exception that should be propagated
85        * must be wrapped inside a <tt>NamingException</tt>.
86        *
87        * @param ctl A non-null control.
88        *
89        * @return A possibly null Control.
90        * @exception NamingException If <tt>ctl</tt> contains invalid data that prevents it
91        * from being used to create a control. A factory should only throw
92        * an exception if it knows how to produce the control (identified by the OID)
93        * but is unable to because of, for example invalid BER data.
94        */
95      public abstract Control getControlInstance(Control ctl) throws NamingException;
96  
97      /**
98        * Creates a control using known control factories.
99        * <p>
100       * The following rule is used to create the control:
101       *<ul>
102       * <li> Use the control factories specified in
103       *    the <tt>LdapContext.CONTROL_FACTORIES</tt> property of the
104       *    environment, and of the provider resource file associated with
105       *    <tt>ctx</tt>, in that order.
106       *    The value of this property is a colon-separated list of factory
107       *    class names that are tried in order, and the first one that succeeds
108       *    in creating the control is the one used.
109       *    If none of the factories can be loaded,
110       *    return <code>ctl</code>.
111       *    If an exception is encountered while creating the control, the
112       *    exception is passed up to the caller.
113       *</ul>
114       * <p>
115       * Note that a control factory
116       * must be public and must have a public constructor that accepts no arguments.
117       * <p>
118       * @param ctl The non-null control object containing the OID and BER data.
119       * @param ctx The possibly null context in which the control is being created.
120       * If null, no such information is available.
121       * @param env The possibly null environment of the context. This is used
122       * to find the value of the <tt>LdapContext.CONTROL_FACTORIES</tt> property.
123       * @return A control object created using <code>ctl</code>; or
124       *         <code>ctl</code> if a control object cannot be created using
125       *         the algorithm described above.
126       * @exception NamingException if a naming exception was encountered
127       *         while attempting to create the control object.
128       *         If one of the factories accessed throws an
129       *         exception, it is propagated up to the caller.
130       * If an error was encountered while loading
131       * and instantiating the factory and object classes, the exception
132       * is wrapped inside a <tt>NamingException</tt> and then rethrown.
133       */
134     public static Control getControlInstance(Control ctl, Context ctx,
135                                              Hashtable<?,?> env)
136         throws NamingException {
137 
138         // Get object factories list from environment properties or
139         // provider resource file.
140         FactoryEnumeration factories = ResourceManager.getFactories(
141             LdapContext.CONTROL_FACTORIES, env, ctx);
142 
143         if (factories == null) {
144             return ctl;
145         }
146 
147         // Try each factory until one succeeds
148         Control answer = null;
149         ControlFactory factory;
150         while (answer == null && factories.hasMore()) {
151             factory = (ControlFactory)factories.next();
152             answer = factory.getControlInstance(ctl);
153         }
154 
155         return (answer != null)? answer : ctl;
156     }
157 }