01: /*
02: * Copyright 2005-2006 The Kuali Foundation.
03: *
04: *
05: * Licensed under the Educational Community License, Version 1.0 (the "License");
06: * you may not use this file except in compliance with the License.
07: * You may obtain a copy of the License at
08: *
09: * http://www.opensource.org/licenses/ecl1.php
10: *
11: * Unless required by applicable law or agreed to in writing, software
12: * distributed under the License is distributed on an "AS IS" BASIS,
13: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14: * See the License for the specific language governing permissions and
15: * limitations under the License.
16: */
17: package org.kuali.rice.resourceloader;
18:
19: import java.util.ArrayList;
20: import java.util.List;
21:
22: /**
23: * Utility class that binds/unbinds the context ClassLoader of the current Thread
24: * using a ThreadLocal.
25: * This class supports re-entrancy by maintaining a stack of context classloaders.
26: * NOTE: maybe implement stricter checks, by matching some contextual object or original
27: * classloader on bind to the unbind so that they are always matched (within a given context)
28: *
29: * @author Kuali Rice Team (kuali-rice@googlegroups.com)
30: */
31: public final class ContextClassLoaderBinder {
32:
33: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
34: .getLogger(ContextClassLoaderBinder.class);
35:
36: /**
37: * Stack of previous context classloaders that should be
38: * restored on unbind
39: */
40: private static final ThreadLocal<List<ClassLoader>> STACK = new ThreadLocal<List<ClassLoader>>() {
41: protected List<ClassLoader> initialValue() {
42: return new ArrayList<ClassLoader>(5);
43: }
44: };
45:
46: private static List<ClassLoader> getStack() {
47: return STACK.get();
48: }
49:
50: public static void bind(ClassLoader cl) {
51: List<ClassLoader> stack = getStack();
52: Thread current = Thread.currentThread();
53: //log.debug("[bind] Switching CCL from " + current.getContextClassLoader() + " to " + cl);
54: // push the current context classloader on the stack
55: stack.add(current.getContextClassLoader());
56: current.setContextClassLoader(cl);
57: }
58:
59: public static void unbind() {
60: List<ClassLoader> stack = getStack();
61: if (stack.size() == 0) {
62: throw new IllegalStateException(
63: "No context classloader to unbind!");
64: }
65: // pop the last context classloader off the stack
66: ClassLoader lastClassLoader = stack.get(stack.size() - 1);
67: //log.debug("[unbind] Switching CCL from " + Thread.currentThread().getContextClassLoader() + " to " + lastClassLoader);
68: stack.remove(stack.size() - 1);
69: Thread.currentThread().setContextClassLoader(lastClassLoader);
70: }
71: }
|