blob: cbd9b8ab853dd527849a996f9bdf5bfeba674d15 [file] [log] [blame]
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.naming.ldap;
import javax.naming.NamingException;
import javax.naming.Context;
import java.util.Hashtable;
import com.sun.naming.internal.FactoryEnumeration;
import com.sun.naming.internal.ResourceManager;
/**
* This abstract class represents a factory for creating LDAPv3 controls.
* LDAPv3 controls are defined in
* <A HREF="http://www.ietf.org/rfc/rfc2251.txt">RFC 2251</A>.
*<p>
* When a service provider receives a response control, it uses control
* factories to return the specific/appropriate control class implementation.
*
* @author Rosanna Lee
* @author Scott Seligman
* @author Vincent Ryan
*
* @see Control
* @since 1.3
*/
public abstract class ControlFactory {
/*
* Creates a new instance of a control factory.
*/
protected ControlFactory() {
}
/**
* Creates a control using this control factory.
*<p>
* The factory is used by the service provider to return controls
* that it reads from the LDAP protocol as specialized control classes.
* Without this mechanism, the provider would be returning
* controls that only contained data in BER encoded format.
*<p>
* Typically, <tt>ctl</tt> is a "basic" control containing
* BER encoded data. The factory is used to create a specialized
* control implementation, usually by decoding the BER encoded data,
* that provides methods to access that data in a type-safe and friendly
* manner.
* <p>
* For example, a factory might use the BER encoded data in
* basic control and return an instance of a VirtualListReplyControl.
*<p>
* If this factory cannot create a control using the argument supplied,
* it should return null.
* A factory should only throw an exception if it is sure that
* it is the only intended factory and that no other control factories
* should be tried. This might happen, for example, if the BER data
* in the control does not match what is expected of a control with
* the given OID. Since this method throws <tt>NamingException</tt>,
* any other internally generated exception that should be propagated
* must be wrapped inside a <tt>NamingException</tt>.
*
* @param ctl A non-null control.
*
* @return A possibly null Control.
* @exception NamingException If <tt>ctl</tt> contains invalid data that prevents it
* from being used to create a control. A factory should only throw
* an exception if it knows how to produce the control (identified by the OID)
* but is unable to because of, for example invalid BER data.
*/
public abstract Control getControlInstance(Control ctl) throws NamingException;
/**
* Creates a control using known control factories.
* <p>
* The following rule is used to create the control:
*<ul>
* <li> Use the control factories specified in
* the <tt>LdapContext.CONTROL_FACTORIES</tt> property of the
* environment, and of the provider resource file associated with
* <tt>ctx</tt>, in that order.
* The value of this property is a colon-separated list of factory
* class names that are tried in order, and the first one that succeeds
* in creating the control is the one used.
* If none of the factories can be loaded,
* return <code>ctl</code>.
* If an exception is encountered while creating the control, the
* exception is passed up to the caller.
*</ul>
* <p>
* Note that a control factory
* must be public and must have a public constructor that accepts no arguments.
* <p>
* @param ctl The non-null control object containing the OID and BER data.
* @param ctx The possibly null context in which the control is being created.
* If null, no such information is available.
* @param env The possibly null environment of the context. This is used
* to find the value of the <tt>LdapContext.CONTROL_FACTORIES</tt> property.
* @return A control object created using <code>ctl</code>; or
* <code>ctl</code> if a control object cannot be created using
* the algorithm described above.
* @exception NamingException if a naming exception was encountered
* while attempting to create the control object.
* If one of the factories accessed throws an
* exception, it is propagated up to the caller.
* If an error was encountered while loading
* and instantiating the factory and object classes, the exception
* is wrapped inside a <tt>NamingException</tt> and then rethrown.
*/
public static Control getControlInstance(Control ctl, Context ctx,
Hashtable<?,?> env)
throws NamingException {
// Get object factories list from environment properties or
// provider resource file.
FactoryEnumeration factories = ResourceManager.getFactories(
LdapContext.CONTROL_FACTORIES, env, ctx);
if (factories == null) {
return ctl;
}
// Try each factory until one succeeds
Control answer = null;
ControlFactory factory;
while (answer == null && factories.hasMore()) {
factory = (ControlFactory)factories.next();
answer = factory.getControlInstance(ctl);
}
return (answer != null)? answer : ctl;
}
}