001 /*
002 * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.naming.ldap;
027
028 import javax.naming.NamingException;
029 import javax.naming.Context;
030
031 import java.util.Hashtable;
032
033 import com.sun.naming.internal.FactoryEnumeration;
034 import com.sun.naming.internal.ResourceManager;
035
036 /**
037 * This abstract class represents a factory for creating LDAPv3 controls.
038 * LDAPv3 controls are defined in
039 * <A HREF="ftp://ftp.isi.edu/in-notes/rfc2251.txt">RFC 2251</A>.
040 *<p>
041 * When a service provider receives a response control, it uses control
042 * factories to return the specific/appropriate control class implementation.
043 *
044 * @author Rosanna Lee
045 * @author Scott Seligman
046 * @author Vincent Ryan
047 * @version 1.19 07/05/05
048 *
049 * @see Control
050 * @since 1.3
051 */
052
053 public abstract class ControlFactory {
054 /*
055 * Creates a new instance of a control factory.
056 */
057 protected ControlFactory() {
058 }
059
060 /**
061 * Creates a control using this control factory.
062 *<p>
063 * The factory is used by the service provider to return controls
064 * that it reads from the LDAP protocol as specialized control classes.
065 * Without this mechanism, the provider would be returning
066 * controls that only contained data in BER encoded format.
067 *<p>
068 * Typically, <tt>ctl</tt> is a "basic" control containing
069 * BER encoded data. The factory is used to create a specialized
070 * control implementation, usually by decoding the BER encoded data,
071 * that provides methods to access that data in a type-safe and friendly
072 * manner.
073 * <p>
074 * For example, a factory might use the BER encoded data in
075 * basic control and return an instance of a VirtualListReplyControl.
076 *<p>
077 * If this factory cannot create a control using the argument supplied,
078 * it should return null.
079 * A factory should only throw an exception if it is sure that
080 * it is the only intended factory and that no other control factories
081 * should be tried. This might happen, for example, if the BER data
082 * in the control does not match what is expected of a control with
083 * the given OID. Since this method throws <tt>NamingException</tt>,
084 * any other internally generated exception that should be propagated
085 * must be wrapped inside a <tt>NamingException</tt>.
086 *
087 * @param ctl A non-null control.
088 *
089 * @return A possibly null Control.
090 * @exception NamingException If <tt>ctl</tt> contains invalid data that prevents it
091 * from being used to create a control. A factory should only throw
092 * an exception if it knows how to produce the control (identified by the OID)
093 * but is unable to because of, for example invalid BER data.
094 */
095 public abstract Control getControlInstance(Control ctl)
096 throws NamingException;
097
098 /**
099 * Creates a control using known control factories.
100 * <p>
101 * The following rule is used to create the control:
102 *<ul>
103 * <li> Use the control factories specified in
104 * the <tt>LdapContext.CONTROL_FACTORIES</tt> property of the
105 * environment, and of the provider resource file associated with
106 * <tt>ctx</tt>, in that order.
107 * The value of this property is a colon-separated list of factory
108 * class names that are tried in order, and the first one that succeeds
109 * in creating the control is the one used.
110 * If none of the factories can be loaded,
111 * return <code>ctl</code>.
112 * If an exception is encountered while creating the control, the
113 * exception is passed up to the caller.
114 *</ul>
115 * <p>
116 * Note that a control factory
117 * must be public and must have a public constructor that accepts no arguments.
118 * <p>
119 * @param ctl The non-null control object containing the OID and BER data.
120 * @param ctx The possibly null context in which the control is being created.
121 * If null, no such information is available.
122 * @param env The possibly null environment of the context. This is used
123 * to find the value of the <tt>LdapContext.CONTROL_FACTORIES</tt> property.
124 * @return A control object created using <code>ctl</code>; or
125 * <code>ctl</code> if a control object cannot be created using
126 * the algorithm described above.
127 * @exception NamingException if a naming exception was encountered
128 * while attempting to create the control object.
129 * If one of the factories accessed throws an
130 * exception, it is propagated up to the caller.
131 * If an error was encountered while loading
132 * and instantiating the factory and object classes, the exception
133 * is wrapped inside a <tt>NamingException</tt> and then rethrown.
134 */
135 public static Control getControlInstance(Control ctl, Context ctx,
136 Hashtable<?, ?> env) 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 }
|