/* | 
|
 * Copyright (c) 1999, 2013, 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;  | 
|
}  | 
|
}  |