001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.naming.ldap;
019:
020: import java.util.Hashtable;
021: import javax.naming.Context;
022: import javax.naming.NamingException;
023: import java.security.AccessController;
024: import java.security.PrivilegedAction;
025:
026: import org.apache.harmony.jndi.internal.EnvironmentReader;
027: import org.apache.harmony.jndi.internal.nls.Messages;
028:
029: /**
030: * This abstract class is used for factories which create controls as used in
031: * LDAPv3. These factories are used by service providers to obtain control
032: * instances when they receive a response control.
033: *
034: * @see Control
035: */
036: public abstract class ControlFactory {
037:
038: /**
039: * Constructs a <code>ControlFactory</code> instance with no parameters.
040: */
041: protected ControlFactory() {
042: super ();
043: }
044:
045: /**
046: * Uses this control factory to create a particular type of <code>Control
047: * </code>
048: * based on the supplied control. It is likely that the supplied control
049: * contains data encoded in BER format as received from an LDAP server.
050: * Returns <code>null</code> if the factory cannot create a
051: * <code>Control</code> else it returns the type of <code>Control</code>
052: * created by the factory.
053: *
054: *
055: * @param c
056: * the supplied control
057: * @throws NamingException
058: * If an error is encountered.
059: * @return the control
060: */
061: public abstract Control getControlInstance(Control c)
062: throws NamingException;
063:
064: /**
065: * Creates a particular type of control based on the supplied control c. It
066: * is likely that the supplied control contains data encoded in BER format
067: * as received from an LDAP server.
068: * <p>
069: * This method tries the factories in LdapContext.CONTROL_FACTORIES, first
070: * from the supplied <code>Hashtable</code> then from the resource
071: * provider files of the supplied <code>Context</code>.
072: * </p>
073: * <p>
074: * It returns the supplied control if no factories are loaded or a control
075: * cannot be created. Otherwise, a new <code>Control</code> instance is
076: * returned.
077: *
078: * @param c
079: * the supplied <code>Control</code> instance
080: * @param ctx
081: * the supplied <code>Context</code> instance
082: * @param h
083: * the supplier JNDI environment properties
084: * @return the supplied control if no factories are loaded or a control
085: * cannot be created, otherwise a new <code>Control</code>
086: * instance
087: * @throws NamingException
088: * If an error is encountered.
089: */
090: public static Control getControlInstance(Control c, Context ctx,
091: Hashtable<?, ?> h) throws NamingException {
092:
093: // obtain control factories from hashtable and provider resource file
094: String fnames[] = EnvironmentReader
095: .getFactoryNamesFromEnvironmentAndProviderResource(h,
096: ctx, LdapContext.CONTROL_FACTORIES);
097:
098: for (String element : fnames) {
099: // new factory instance by its class name
100: ControlFactory factory = null;
101: try {
102: factory = (ControlFactory) classForName(element)
103: .newInstance();
104: } catch (Exception e) {
105: continue;
106: }
107: // try obtaining a Control using the factory
108: Control control = factory.getControlInstance(c);
109: // if a Control is obtained successfully, return it
110: if (null != control) {
111: return control;
112: }
113: }
114:
115: // all factories failed, return the input argument c
116: return c;
117: }
118:
119: /*
120: * Use the context class loader or the system class loader to load the
121: * specified class, in a privileged manner.
122: */
123: private static Class<?> classForName(final String className)
124: throws ClassNotFoundException {
125:
126: Class<?> cls = AccessController
127: .doPrivileged(new PrivilegedAction<Class<?>>() {
128: public Class<?> run() {
129: // try thread context class loader first
130: try {
131: return Class.forName(className, true,
132: Thread.currentThread()
133: .getContextClassLoader());
134: } catch (ClassNotFoundException e) {
135: // Ignored
136: }
137: // try system class loader second
138: try {
139: return Class.forName(className, true,
140: ClassLoader.getSystemClassLoader());
141: } catch (ClassNotFoundException e) {
142: // Ignored
143: }
144: // return null, if fail to load class
145: return null;
146: }
147: });
148:
149: if (cls == null) {
150: // jndi.1C=class {0} not found
151: throw new ClassNotFoundException(Messages.getString(
152: "jndi.1C", className)); //$NON-NLS-1$
153: }
154:
155: return cls;
156: }
157:
158: }
|