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.spi;
019:
020: import java.net.URL;
021: import java.net.URLClassLoader;
022: import java.security.AccessController;
023: import java.security.PrivilegedAction;
024: import java.util.Enumeration;
025: import java.util.Hashtable;
026: import java.util.StringTokenizer;
027:
028: import javax.naming.CannotProceedException;
029: import javax.naming.Context;
030: import org.apache.harmony.jndi.internal.EnvironmentReader;
031: import org.apache.harmony.jndi.internal.UrlParser;
032: import org.apache.harmony.jndi.internal.nls.Messages;
033:
034: import javax.naming.Name;
035: import javax.naming.NamingException;
036: import javax.naming.NoInitialContextException;
037: import javax.naming.RefAddr;
038: import javax.naming.Reference;
039: import javax.naming.Referenceable;
040: import javax.naming.StringRefAddr;
041:
042: /**
043: * The <code>NamingManager</code> class should not be instantiated although it
044: * can be extended by classes within the <code>javax.naming.spi</code> package -
045: * see {@link DirectoryManager}. All its methods are static.
046: * <p>
047: * The methods are used by service providers for accessing object and state
048: * factories and for determining continuation contexts. Many of the methods
049: * create objects. These may be <code>Context</code> objects or objects
050: * referred to by the naming service.
051: * </p>
052: * <p>
053: * The <code>Name</code> and <code>Hashtable</code> arguments passed to the
054: * <code>NamingManager</code> methods remain owned purely by the calling
055: * method. They must not be changed or referenced.
056: * </p>
057: * <p>
058: * It should be noted that it is possible for an application to access a
059: * namespace other than that supplied by the default <code>InitialContext</code>
060: * (as specified by <code>Context.INITIAL_CONTEXT_FACTORY</code>). It is
061: * possible to call the following <code>InitialContext</code> methods passing
062: * a URL string either as the <code>String</code> or <code>Name</code>
063: * parameter: <code>lookup, bin, rebind, unbind, rename, list, listBindings,
064: * destroySubcontext, createSubcontext, lookupLink, getNameParser</code>.
065: * This allows you to have one <code>InitialContext</code> object where these
066: * methods usually use the default initial context but access a URL
067: * <code>Context</code> instead when invoked with a URL string.
068: * </p>
069: * <p>
070: * A URL string is of the format abc:\nnnnnn where abc is the scheme of the URL.
071: * (See <code>InitialContext</code> where it refers to RFC1738.) When a URL
072: * string is supplied to those <code>InitialContext</code> methods, a URL
073: * context is used instead of the default initial context when performing that
074: * method. URL context factories are used to create URL contexts. A URL context
075: * factory is really just a service provider's implementation of an
076: * <code>ObjectFactory</code>. It is not essential that a service provider
077: * supplies one if they do not wish to support URL <code>Contexts.</code>
078: * </p>
079: * <p>
080: * See the <code>getURLContext</code> method for a description of how a URL
081: * context factory is located.
082: * </p>
083: * <p>
084: * Please note that multithreaded access to this class must be safe. For
085: * example, for thread safety, it should not be possible for one thread to read
086: * the installed <code>InitialContextFactoryBuilder</code> or
087: * <code>ObjectFactoryBuilder</code> while another thread is in the process of
088: * setting it.
089: * </p>
090: * <p>
091: * Also note that privileges should be granted to get the context classloader
092: * and to read the resource files.
093: * </p>
094: *
095: * @see DirectoryManager
096: */
097: public class NamingManager {
098:
099: /**
100: * The property name of <code>CannotProceedException</code> in a context's
101: * environment.
102: */
103: public static final String CPE = "java.naming.spi.CannotProceedException"; //$NON-NLS-1$
104:
105: static InitialContextFactoryBuilder icfb;
106:
107: static ObjectFactoryBuilder ofb;
108:
109: NamingManager() {
110: super ();
111: // package private to prevent it being instanced but make it can be
112: // subclassed by DirectoryManager
113: }
114:
115: /**
116: * Install an <code>InitialContextFactoryBuilder</code>. Once this has
117: * been set it cannot be reset. Attempts to do so cause an
118: * <code>IllegalStateException</code>. The builder can only be installed
119: * if the security policy allows the setting of the factory.
120: *
121: * @param icfb
122: * the builder to be installed - can be null, but then no builder
123: * is installed.
124: * @throws IllegalStateException
125: * if an builder has already been installed.
126: * @throws SecurityException
127: * is a security error prevents the installation.
128: * @throws NamingException
129: * for other errors encountered.
130: */
131: public static void setInitialContextFactoryBuilder(
132: InitialContextFactoryBuilder icfb)
133: throws IllegalStateException, SecurityException,
134: NamingException {
135: // check security access
136: SecurityManager sm = System.getSecurityManager();
137: if (null != sm) {
138: sm.checkSetFactory();
139: }
140: synchronized (NamingManager.class) {
141: if (null != NamingManager.icfb) {
142: // jndi.1E=InitialContextFactoryBuilder cannot be reset
143: throw new IllegalStateException(Messages
144: .getString("jndi.1E")); //$NON-NLS-1$
145: }
146: NamingManager.icfb = icfb;
147: }
148: }
149:
150: /**
151: * Returns true when an <code>InitialContextFactoryBuilder</code> has been
152: * installed.
153: *
154: * @return true when an <code>InitialContextFactoryBuilder</code> has been
155: * installed.
156: */
157: public static boolean hasInitialContextFactoryBuilder() {
158: return null != icfb;
159: }
160:
161: /**
162: * Install an <code>ObjectFactoryBuilder</code>. Once this has been set
163: * it cannot be reset. Attempts to do so cause an
164: * <code>IllegalStateException</code>. The builder can only be installed
165: * if the security policy allows the setting of the factory.
166: *
167: * @param ofb
168: * the <code>ObjectFactoryBuilder</code> to be installed - can
169: * be null, but then no builder is installed.
170: * @throws IllegalStateException
171: * if an <code>ObjectFactoryBuilder</code> has already been
172: * installed.
173: * @throws SecurityException
174: * is a security error prevents the installation.
175: * @throws NamingException
176: * for other errors encountered.
177: */
178: public static synchronized void setObjectFactoryBuilder(
179: ObjectFactoryBuilder ofb) throws IllegalStateException,
180: SecurityException, NamingException {
181:
182: if (null != NamingManager.ofb) {
183: // jndi.1F=ObjectFactoryBuilder cannot be reset
184: throw new IllegalStateException(Messages
185: .getString("jndi.1F")); //$NON-NLS-1$
186: }
187:
188: // check security access
189: SecurityManager sm = System.getSecurityManager();
190: if (null != sm) {
191: sm.checkSetFactory();
192: }
193:
194: NamingManager.ofb = ofb;
195: }
196:
197: /**
198: * Create an <code>InitialContext</code> from either a previously
199: * installed <code>InitialContextFactoryBuilder</code> or from the
200: * <code>Context.INITIAL_CONTEXT_FACTORY</code> property in the supplied
201: * <code> Hashtable h</code> if no builder is installed. An installed
202: * <code>InitialContextFactoryBuilder</code> can generate a factory which
203: * can be used to create the <code>InitialContext</code>. The
204: * <code>Context.INITIAL_CONTEXT_FACTORY</code> property contains the
205: * class of a factory which can be used to create the
206: * <code>InitialContext</code>.
207: *
208: * @param h
209: * a hashtable containing properties and values - may be null
210: * @return an <code>InitialContext</code>
211: * @throws NoInitialContextException
212: * if the <code>InitialContext</code> cannot be created.
213: * @throws NamingException
214: */
215: public static Context getInitialContext(Hashtable<?, ?> h)
216: throws NoInitialContextException, NamingException {
217:
218: // if InitialContextFactoryBuilder is set
219: if (null != icfb) {
220: // create InitialContext using builder
221: return icfb.createInitialContextFactory(h)
222: .getInitialContext(h);
223: }
224:
225: // create InitialContext using factory specified in hashtable
226: try {
227: // get factory class name
228: String factoryClassName = (String) h
229: .get(Context.INITIAL_CONTEXT_FACTORY);
230: // new factory instance
231: Class<?> factoryClass = classForName(factoryClassName);
232: InitialContextFactory factory = (InitialContextFactory) factoryClass
233: .newInstance();
234: // create initial context instance using the factory
235: return factory.getInitialContext(h);
236: } catch (NamingException e) {
237: // throw NamingException
238: throw e;
239: } catch (Exception e) {
240: // failed, throw NoInitialContextException
241: // jndi.20=Failed to create InitialContext using factory specified
242: // in hashtable {0}
243: NamingException nex = new NoInitialContextException(
244: Messages.getString("jndi.20", h)); //$NON-NLS-1$
245: nex.setRootCause(e);
246: throw nex;
247: }
248: }
249:
250: /**
251: * Create an object from either a previously installed
252: * <code>ObjectFactoryBuilder</code> or from a supplied reference or from
253: * the <code>Context.OBJECT_FACTORIES</code> property in the supplied
254: * <code>Hashtable h</code>.
255: * <p>
256: * An installed <code>ObjectFactoryBuilder</code> can generate a factory
257: * which can be used to create the object instance to return to caller. Any
258: * encountered exceptions are thrown.
259: * </p>
260: * <p>
261: * If an <code>ObjectFactoryBuilder</code> has not been installed then the
262: * supplied <code>Object o</code> may provide a <code>Reference</code>
263: * or <code>Referenceable</code> object. If so, then that
264: * <code>Object o</code> may have an associated class in a factory which
265: * could be loaded and used to create the object instance. If the factory
266: * class cannot be loaded then the <code>URLClassLoader</code> may be able
267: * to load a class from the list of URLs specified in the reference's
268: * factory class location. Any exceptions encountered are passed up.
269: * </p>
270: * <p>
271: * If a reference is supplied but no factory class can be loaded from it
272: * then this method returns the supplied object <code>o</code>.
273: * </p>
274: * <p>
275: * If a factory class loads successfully and can then be used to create an
276: * object instance then that instance is returned to the caller.
277: * </p>
278: * <p>
279: * If no factory name was associated with the <code>Reference</code>
280: * object <code>o</code> then see whether the <code>Reference</code> or
281: * <code>Referenceable</code> object has any <code>StringRefAddrs</code>
282: * of address type URL or url in its address list. For each entry in the
283: * list, in the order they appear in the list, it may be possible to use the
284: * URL factory to create the object. A URL in a <code>StringRefAddr</code>
285: * should have a scheme which can be used to locate the associated URL
286: * context factory in the same way as in the <code>getURLContext</code>
287: * method. (The scheme is the part which comes before :\. For example the
288: * URL http://www.apache.org has the scheme http.) A URL with no scheme
289: * would be ignored for these purposes.
290: * </p>
291: * <p>
292: * If no <code>ObjectFactoryBuilder</code> was installed, no factory class
293: * name is supplied with a <code>Reference</code> and no URL contexts
294: * succeeded in creating an <code>Object</code> then try the factories in
295: * <code>Context.OBJECT_FACTORIES</code> for this environment. Also try
296: * the provider resource file belonging to the context <code>c</code>.
297: * (See <code>Context</code> description for details of Provider resource
298: * files.) If any factory throws an exception then pass that back to the
299: * caller - no further factories are tried.
300: * </p>
301: * <p>
302: * If all factories fail to load or create the <code>Object</code> then
303: * return the argument object <code>o</code> as the returned object.
304: * </p>
305: *
306: * @param o
307: * an object which may provide reference or location information.
308: * May be null.
309: * @param n
310: * The name of the <code>Object</code> relative to the default
311: * initial context(or relative to the Context c if it is
312: * supplied)
313: * @param c
314: * the <code>Context</code> to which the <code>Name</code> is
315: * relative
316: * @param h
317: * a <code>Hashtable</code> containing environment properties
318: * and values - may be null
319: * @return a new <code>Object</code> or the supplied <code>Object o</code>
320: * if one cannot be created.
321: * @throws NamingException
322: * if one is encountered
323: * @throws Exception
324: * if any other exception is encountered
325: */
326: public static Object getObjectInstance(Object o, Name n, Context c,
327: Hashtable<?, ?> h) throws NamingException, Exception {
328:
329: // 1. try ObjectFactoryBuilder, if it is set
330: if (null != ofb) {
331: // use the builder to create an object factory
332: ObjectFactory factory = ofb.createObjectFactory(o, h);
333: // get object instance using the factory and return
334: return factory.getObjectInstance(o, n, c, h);
335: }
336:
337: // 2. see whether o is a Referenceable or a Reference
338: Reference ref = null;
339: if (o instanceof Referenceable) {
340: ref = ((Referenceable) o).getReference();
341: }
342: if (o instanceof Reference) {
343: ref = (Reference) o;
344: }
345: // if o is a Referenceable or a Reference
346: if (null != ref) {
347: // if a factory class name is supplied by the reference, use it to
348: // create
349: if (null != ref.getFactoryClassName()) {
350: return getObjectInstanceByFactoryInReference(ref, o, n,
351: c, h);
352: }
353: // see if ref has any StringRefAddrs of address type URL,
354: Object result = getObjectInstanceByUrlRefAddr(n, c, h, ref);
355: // if success, return it
356: if (null != result) {
357: return result;
358: }
359: }
360:
361: // 3. try Context.OBJECT_FACTORIES
362: Object result = getObjectInstanceByObjectFactory(o, n, c, h);
363: if (null != result) {
364: return result;
365: }
366:
367: // all failed, just return o
368: return o;
369: }
370:
371: private static Object getObjectInstanceByObjectFactory(Object o,
372: Name n, Context c, Hashtable<?, ?> h)
373: throws NamingException, Exception {
374: // obtain object factories from hashtable and service provider resource
375: // file
376: String fnames[] = EnvironmentReader
377: .getFactoryNamesFromEnvironmentAndProviderResource(h,
378: c, Context.OBJECT_FACTORIES);
379: for (String element : fnames) {
380: // new factory instance by its class name
381: ObjectFactory factory = null;
382: try {
383: factory = (ObjectFactory) classForName(element)
384: .newInstance();
385: } catch (Exception e) {
386: continue;
387: }
388: // create object using factory
389: Object obj = factory.getObjectInstance(o, n, c, h);
390: if (null != obj) {
391: return obj;
392: }
393: }
394: // no object factory succeeded, return null
395: return null;
396: }
397:
398: private static Object getObjectInstanceByUrlRefAddr(Name n,
399: Context c, Hashtable<?, ?> h, Reference ref)
400: throws NamingException {
401: // obtain pkg prefixes from hashtable and service provider resource file
402: String pkgPrefixes[] = EnvironmentReader
403: .getFactoryNamesFromEnvironmentAndProviderResource(h,
404: c, Context.URL_PKG_PREFIXES);
405: // for each RefAddr
406: Enumeration<RefAddr> enumeration = ref.getAll();
407: while (enumeration.hasMoreElements()) {
408: RefAddr addr = enumeration.nextElement();
409: // if it is StringRefAddr and type is URL
410: if (addr instanceof StringRefAddr
411: && addr.getType().equalsIgnoreCase("URL")) { //$NON-NLS-1$
412: // get the url address
413: String url = (String) ((StringRefAddr) addr)
414: .getContent();
415: // try create using url context factory
416: Object obj = getObjectInstanceByUrlContextFactory(url,
417: n, c, h, pkgPrefixes, UrlParser.getScheme(url));
418: // if success, return the created obj
419: if (null != obj) {
420: return obj;
421: }
422: }
423: }
424: // failed to create using any StringRefAddr of address type URL, return
425: // null
426: return null;
427: }
428:
429: private static Object getObjectInstanceByUrlContextFactory(
430: String url, Name n, Context c, Hashtable<?, ?> h,
431: String pkgPrefixes[], String schema) throws NamingException {
432: // if schema is empty or null, fail, return null
433: if (null == schema || 0 == schema.length()) {
434: return null;
435: }
436:
437: for (String element : pkgPrefixes) {
438: ObjectFactory factory = null;
439: try {
440: // create url context factory instance
441: String clsName = element + "." //$NON-NLS-1$
442: + schema + "." //$NON-NLS-1$
443: + schema + "URLContextFactory"; //$NON-NLS-1$
444: factory = (ObjectFactory) classForName(clsName)
445: .newInstance();
446: } catch (Exception e) {
447: // failed to create factory, continue trying
448: continue;
449: }
450: try {
451: // create obj using url context factory
452: Object obj = factory.getObjectInstance(url, n, c, h);
453: // if create success, return it
454: if (null != obj) {
455: return obj;
456: }
457: } catch (Exception e) {
458: // throw NamingException, if factory fails
459: if (e instanceof NamingException) {
460: throw (NamingException) e;
461: }
462: // jndi.21=Failed to create object instance
463: NamingException nex = new NamingException(Messages
464: .getString("jndi.21")); //$NON-NLS-1$
465: nex.setRootCause(e);
466: throw nex;
467: }
468: }
469: // fail to create using url context factory, return null
470: return null;
471: }
472:
473: private static Object getObjectInstanceByFactoryInReference(
474: Reference ref, Object o, Name n, Context c,
475: Hashtable<?, ?> h) throws Exception {
476: ObjectFactory factory = null;
477:
478: // try load the factory by its class name
479: try {
480: factory = (ObjectFactory) classForName(
481: ref.getFactoryClassName()).newInstance();
482: } catch (ClassNotFoundException e) {
483: // Ignore.
484: }
485:
486: // try load the factory from its class location
487: if (null == factory && null != ref.getFactoryClassLocation()) {
488: factory = (ObjectFactory) loadFactoryFromLocation(ref
489: .getFactoryClassName(), ref
490: .getFactoryClassLocation());
491: }
492: // if factory cannot be loaded
493: if (null == factory) {
494: // return o
495: return o;
496: }
497:
498: // get object instance using the factory and return it
499: return factory.getObjectInstance(ref, n, c, h);
500: }
501:
502: /*
503: * If cannot load class, return null. Throws any exceptions except
504: * ClassNotFoundException
505: */
506: private static Object loadFactoryFromLocation(String clsName,
507: String location) throws Exception {
508:
509: // convert location into an array of URL, separated by ' '
510: StringTokenizer st = new StringTokenizer(location, " "); //$NON-NLS-1$
511: URL urls[] = new URL[st.countTokens()];
512: for (int i = 0; i < urls.length; i++) {
513: urls[i] = new URL(st.nextToken());
514: }
515:
516: // new a URLClassLoader from the URLs
517: URLClassLoader l = new URLClassLoader(urls);
518:
519: // try load factory by URLClassLoader
520: try {
521: // return the new instance
522: return l.loadClass(clsName).newInstance();
523: } catch (ClassNotFoundException e) {
524: // return null if class loading failed
525: return null;
526: }
527: }
528:
529: /**
530: * Get the state of an Object.
531: * <p>
532: * The <code>Context.STATE_FACTORIES</code> property from the
533: * <code>Hashtable h</code> together with the
534: * <code>Context.STATE_FACTORIES</code> property from the provider
535: * resource file of the <code>Context c</code> provides the list of
536: * factories tried to get an object's state.
537: * </p>
538: * <p>
539: * Each factory in the list is attempted to be loaded using the context
540: * class loader. Once a class is loaded then it can be used to create a new
541: * instance of it to obtain the factory which can then use its
542: * <code>getStateToBind</code> to find the return object. Once an object
543: * is found then it is not necessary to examine further factories and the
544: * object is returned it as the return parameter.
545: * </p>
546: * <p>
547: * If no factory is loaded or all loaded factories fail to return an object
548: * then return the supplied <code>Object o</code> as the return param.
549: * </p>
550: * <p>
551: * Note for service provider implementors: Classes which implement the
552: * <code>StateFactory</code> interface must be public with a public
553: * constructor that has no parameters.
554: * </p>
555: *
556: * @param o
557: * an object which may provide reference or location information.
558: * May be null.
559: * @param n
560: * the name of the <code>Object</code> relative to the default
561: * initial context (or relative to the Context c if it is
562: * supplied)
563: * @param c
564: * the <code>Context</code> to which the <code>Name</code> is
565: * relative
566: * @param h
567: * a <code>Hashtable</code> containing environment properties
568: * and values - may be null
569: * @return the state of the specified object
570: * @throws NamingException
571: * if one is encountered
572: */
573: public static Object getStateToBind(Object o, Name n, Context c,
574: Hashtable<?, ?> h) throws NamingException {
575:
576: // obtain state factories from hashtable and service provider resource
577: // file
578: String fnames[] = EnvironmentReader
579: .getFactoryNamesFromEnvironmentAndProviderResource(h,
580: c, Context.STATE_FACTORIES);
581:
582: for (String element : fnames) {
583: // new factory instance by its class name
584: StateFactory factory = null;
585: try {
586: factory = (StateFactory) classForName(element)
587: .newInstance();
588: } catch (Exception e) {
589: continue;
590: }
591: // try obtain state using the factory
592: Object state = factory.getStateToBind(o, n, c, h);
593: // if a state obtained successfully, return it
594: if (null != state) {
595: return state;
596: }
597: }
598:
599: // all factories failed, return the input argument o
600: return o;
601: }
602:
603: /**
604: * Creates a URL <code>Context</code> which can subsequently be used to
605: * resolve any URLs with the URL scheme s. A <code>URLContextFactory</code>
606: * is a type of <code>ObjectFactory</code> used to create a
607: * <code>URLContext</code> when <code>getObjectInstance</code> is
608: * invoked with the <code>Object o</code> set to null (see the description
609: * of <code>ObjectFactory</code>).
610: * <p>
611: * This <code>getURLContext</code> method tries to locate the
612: * <code>URLContextFactory</code> based on the
613: * <code>Context.URL_PKG_PREFIXES</code> property which contains the
614: * prefixes to be tried as the start of the package name. (See
615: * <code>Context</code>).
616: * </p>
617: * <p>
618: * Each package prefix entry (and finally the default value) are tried to
619: * find the class which can be used to create the Context.
620: * </p>
621: * <p>
622: * A full class name is derived as
623: * <code>packageprefix.s.sURLContextFactory</code> where <code>s</code>
624: * is the scheme.
625: * </p>
626: * <p>
627: * For example if a scheme is abc and the package prefix to try is com.ibm
628: * then the factory class to try is
629: * <code>com.ibm.abc.abcURLContextFactory</code>. Once a factory is
630: * created then a <code>Context</code> is created using the special use of
631: * <code>ObjectFactory.getObjectInstance</code>.
632: * </p>
633: * <p>
634: * Once a first factory is created, it is used to create the context, and NO
635: * further attempts will be made on other pkg prefixes.
636: * </p>
637: *
638: * @param schema
639: * the URL scheme to which the Context will relate
640: * @param envmt
641: * a <code>Hashtable</code> containing environment properties
642: * and values - may be null
643: * @return the URL <code>Context</code> or null if no
644: * <code>URLContextFactory</code> instance can be created and
645: * therefore a Context cannot be created.
646: * @throws NamingException
647: * if one is encountered.
648: */
649: public static Context getURLContext(String schema,
650: Hashtable<?, ?> envmt) throws NamingException {
651:
652: if (null == schema || 0 == schema.length() || null == envmt) {
653: return null;
654: }
655:
656: // obtain pkg prefixes from hashtable
657: String pkgPrefixes[] = EnvironmentReader
658: .getFactoryNamesFromEnvironmentAndProviderResource(
659: envmt, null, Context.URL_PKG_PREFIXES);
660:
661: for (String element : pkgPrefixes) {
662: // create factory instance
663: ObjectFactory factory;
664: try {
665: String clsName = element + "." //$NON-NLS-1$
666: + schema + "." //$NON-NLS-1$
667: + schema + "URLContextFactory"; //$NON-NLS-1$
668: factory = (ObjectFactory) classForName(clsName)
669: .newInstance();
670: } catch (Exception ex) {
671: // fail to create factory, continue to try another
672: continue;
673: }
674: try {
675: // create url context using the factory, and return it
676: return (Context) factory.getObjectInstance(null, null,
677: null, envmt);
678: } catch (NamingException e) {
679: // find NamingException, throw it
680: throw e;
681: } catch (Exception e) {
682: // other exception, throw as NamingException
683: // jndi.22=other exception happens: {0}
684: NamingException nex = new NamingException(Messages
685: .getString("jndi.22", e.toString())); //$NON-NLS-1$
686: nex.setRootCause(e);
687: throw nex;
688: }
689: }
690:
691: // cannot create context instance from any pkg prefixes, return null
692: return null;
693: }
694:
695: /**
696: * Create the next context when using federation. All the information
697: * required to do this is contained in the
698: * <code>CannotProceedException</code> <code>e</code>. If the resolved
699: * object is null then throw the supplied
700: * <code>CannotProceedException</code> <code>e</code> using the stack
701: * details from this thread. The resolved object in <code>e</code> may
702: * already be a <code>Context</code>. This is the case where the service
703: * provider gives an explicit pointer to the next naming system. A Context
704: * object is returned as the continuation context, but need not be the same
705: * object instance as the resolved object.
706: * <p>
707: * If the resolved object is not already a <code>Context</code> then it is
708: * necessary to use the resolved object together with the
709: * <code>altName</code> name, the <code>altNameCtx</code> context and
710: * the environment hashtable to get an instance of the object. This should
711: * then be a context which is returned as the continuation context. If an
712: * instance cannot be obtained then throw the supplied
713: * <code>CannotProceedException</code> using the stack details from this
714: * thread.
715: * </p>
716: * <p>
717: * This method is responsible for setting the property denoted by the
718: * <code>CPE</code> string to be the supplied
719: * <code>CannotProceedException</code> for the exception <code>e</code>
720: * environment. The continuation context should then inherit this property.
721: * </p>
722: *
723: * @param cpe
724: * the <code>CannotProceedException</code> generated by the
725: * context of the previous naming system when it can proceed no
726: * further.
727: * @return the next Context when using federation
728: * @throws NamingException
729: * if the resolved object is null or if a context cannot be
730: * obtained from it either directly or indirectly.
731: */
732: @SuppressWarnings("unchecked")
733: public static Context getContinuationContext(
734: CannotProceedException cpe) throws NamingException {
735:
736: Context ctx = null;
737:
738: // set CPE property of the env
739: if (cpe.getEnvironment() == null) {
740: cpe
741: .setEnvironment(new Hashtable<String, CannotProceedException>());
742: }
743: ((Hashtable<String, CannotProceedException>) cpe
744: .getEnvironment()).put(CPE, cpe);
745:
746: // if resolved object is null
747: if (null == cpe.getResolvedObj()) {
748: // re-throw cpe
749: cpe.fillInStackTrace();
750: throw cpe;
751: }
752:
753: // if cpe's resolved obj is Context
754: if (cpe.getResolvedObj() instanceof Context) {
755: // accept it as the continuation context
756: ctx = (Context) cpe.getResolvedObj();
757: } else {
758: // otherwise, call getObjectInstance() to get a context instance
759: try {
760: ctx = (Context) getObjectInstance(cpe.getResolvedObj(),
761: cpe.getAltName(), cpe.getAltNameCtx(), cpe
762: .getEnvironment());
763: } catch (Exception ex) {
764: // throw back CPE in case of any exception
765: throw cpe;
766: }
767: // if ctx cannot be obtained
768: if (null == ctx) {
769: // re-throw CPE
770: cpe.fillInStackTrace();
771: throw cpe;
772: }
773: }
774:
775: // return the continuation context
776: return ctx;
777: }
778:
779: private static Class<?> classForName(final String className)
780: throws ClassNotFoundException {
781:
782: Class<?> cls = AccessController
783: .doPrivileged(new PrivilegedAction<Class<?>>() {
784: public Class<?> run() {
785: // try thread context class loader first
786: try {
787: return Class.forName(className, true,
788: Thread.currentThread()
789: .getContextClassLoader());
790: } catch (ClassNotFoundException e) {
791: // Ignored.
792: }
793: // try system class loader second
794: try {
795: return Class.forName(className, true,
796: ClassLoader.getSystemClassLoader());
797: } catch (ClassNotFoundException e1) {
798: // Ignored.
799: }
800: // return null, if fail to load class
801: return null;
802: }
803: });
804:
805: if (cls == null) {
806: // jndi.1C=class {0} not found
807: throw new ClassNotFoundException(Messages.getString(
808: "jndi.1C", className)); //$NON-NLS-1$
809: }
810:
811: return cls;
812: }
813:
814: }
|