/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.naming; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingException; /** * Handles the associations : * <ul> * <li>Object with a NamingContext</li> * <li>Calling thread with a NamingContext</li> * <li>Calling thread with object bound to the same naming context</li> * <li>Thread context class loader with a NamingContext</li> * <li>Thread context class loader with object bound to the same * NamingContext</li> * </ul> * The objects are typically Catalina Server or Context objects. * * @author Remy Maucherat */ public class ContextBindings { // -------------------------------------------------------------- Variables /** * Bindings object - naming context. Keyed by object. */ private static final Hashtable<Object,Context> objectBindings = new Hashtable<>(); /** * Bindings thread - naming context. Keyed by thread. */ private static final Hashtable<Thread,Context> threadBindings = new Hashtable<>(); /** * Bindings thread - object. Keyed by thread. */ private static final Hashtable<Thread,Object> threadObjectBindings = new Hashtable<>(); /** * Bindings class loader - naming context. Keyed by class loader. */ private static final Hashtable<ClassLoader,Context> clBindings = new Hashtable<>(); /** * Bindings class loader - object. Keyed by class loader. */ private static final Hashtable<ClassLoader,Object> clObjectBindings = new Hashtable<>(); /** * The string manager for this package. */ protected static final StringManager sm = StringManager.getManager(ContextBindings.class); // --------------------------------------------------------- Public Methods /** * Binds an object and a naming context. * * @param obj Object to bind with naming context * @param context Associated naming context instance */ public static void bindContext(Object obj, Context context) { bindContext(obj, context, null); } /** * Binds an object and a naming context. * * @param obj Object to bind with naming context * @param context Associated naming context instance * @param token Security token */ public static void bindContext(Object obj, Context context, Object token) { if (ContextAccessController.checkSecurityToken(obj, token)) { objectBindings.put(obj, context); } } /** * Unbinds an object and a naming context. * * @param obj Object to unbind * @param token Security token */ public static void unbindContext(Object obj, Object token) { if (ContextAccessController.checkSecurityToken(obj, token)) { objectBindings.remove(obj); } } /** * Retrieve a naming context. * * @param obj Object bound to the required naming context */ static Context getContext(Object obj) { return objectBindings.get(obj); } /** * Binds a naming context to a thread. * * @param obj Object bound to the required naming context * @param token Security token * * @throws NamingException If no naming context is bound to the provided * object */ public static void bindThread(Object obj, Object token) throws NamingException { if (ContextAccessController.checkSecurityToken(obj, token)) { Context context = objectBindings.get(obj); if (context == null) { throw new NamingException( sm.getString("contextBindings.unknownContext", obj)); } threadBindings.put(Thread.currentThread(), context); threadObjectBindings.put(Thread.currentThread(), obj); } } /** * Unbinds a thread and a naming context. * * @param obj Object bound to the required naming context * @param token Security token */ public static void unbindThread(Object obj, Object token) { if (ContextAccessController.checkSecurityToken(obj, token)) { threadBindings.remove(Thread.currentThread()); threadObjectBindings.remove(Thread.currentThread()); } } /** * Retrieves the naming context bound to the current thread. * * @return The naming context bound to the current thread. * * @throws NamingException If no naming context is bound to the current * thread */ public static Context getThread() throws NamingException { Context context = threadBindings.get(Thread.currentThread()); if (context == null) { throw new NamingException (sm.getString("contextBindings.noContextBoundToThread")); } return context; } /** * Retrieves the name of the object bound to the naming context that is also * bound to the current thread. */ static String getThreadName() throws NamingException { Object obj = threadObjectBindings.get(Thread.currentThread()); if (obj == null) { throw new NamingException (sm.getString("contextBindings.noContextBoundToThread")); } return obj.toString(); } /** * Tests if current thread is bound to a naming context. * * @return <code>true</code> if the current thread is bound to a naming * context, otherwise <code>false</code> */ public static boolean isThreadBound() { return threadBindings.containsKey(Thread.currentThread()); } /** * Binds a naming context to a class loader. * * @param obj Object bound to the required naming context * @param token Security token * @param classLoader The class loader to bind to the naming context * * @throws NamingException If no naming context is bound to the provided * object */ public static void bindClassLoader(Object obj, Object token, ClassLoader classLoader) throws NamingException { if (ContextAccessController.checkSecurityToken(obj, token)) { Context context = objectBindings.get(obj); if (context == null) { throw new NamingException (sm.getString("contextBindings.unknownContext", obj)); } clBindings.put(classLoader, context); clObjectBindings.put(classLoader, obj); } } /** * Unbinds a naming context and a class loader. * * @param obj Object bound to the required naming context * @param token Security token * @param classLoader The class loader bound to the naming context */ public static void unbindClassLoader(Object obj, Object token, ClassLoader classLoader) { if (ContextAccessController.checkSecurityToken(obj, token)) { Object o = clObjectBindings.get(classLoader); if (o == null || !o.equals(obj)) { return; } clBindings.remove(classLoader); clObjectBindings.remove(classLoader); } } /** * Retrieves the naming context bound to a class loader. * * @return the naming context bound to current class loader or one of its * parents * * @throws NamingException If no naming context was bound */ public static Context getClassLoader() throws NamingException { ClassLoader cl = Thread.currentThread().getContextClassLoader(); Context context = null; do { context = clBindings.get(cl); if (context != null) { return context; } } while ((cl = cl.getParent()) != null); throw new NamingException(sm.getString("contextBindings.noContextBoundToCL")); } /** * Retrieves the name of the object bound to the naming context that is also * bound to the thread context class loader. */ static String getClassLoaderName() throws NamingException { ClassLoader cl = Thread.currentThread().getContextClassLoader(); Object obj = null; do { obj = clObjectBindings.get(cl); if (obj != null) { return obj.toString(); } } while ((cl = cl.getParent()) != null); throw new NamingException (sm.getString("contextBindings.noContextBoundToCL")); } /** * Tests if the thread context class loader is bound to a context. * * @return <code>true</code> if the thread context class loader or one of * its parents is bound to a naming context, otherwise * <code>false</code> */ public static boolean isClassLoaderBound() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); do { if (clBindings.containsKey(cl)) { return true; } } while ((cl = cl.getParent()) != null); return false; } }