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: */package org.apache.openejb.core;
017:
018: import java.util.HashMap;
019: import java.util.List;
020: import java.util.concurrent.CopyOnWriteArrayList;
021:
022: import org.apache.openejb.util.LogCategory;
023: import org.apache.openejb.util.Logger;
024:
025: public class ThreadContext {
026: private static final Logger log = Logger.getInstance(
027: LogCategory.OPENEJB, "org.apache.openejb.util.resources");
028: private static final ThreadLocal<ThreadContext> threadStorage = new ThreadLocal<ThreadContext>();
029: private static final List<ThreadContextListener> listeners = new CopyOnWriteArrayList<ThreadContextListener>();
030:
031: public static ThreadContext getThreadContext() {
032: ThreadContext threadContext = threadStorage.get();
033: return threadContext;
034: }
035:
036: public static ThreadContext enter(ThreadContext newContext) {
037: if (newContext == null) {
038: throw new NullPointerException("newContext is null");
039: }
040:
041: // set the thread context class loader
042: newContext.oldClassLoader = Thread.currentThread()
043: .getContextClassLoader();
044: Thread.currentThread().setContextClassLoader(
045: newContext.deploymentInfo.getClassLoader());
046:
047: // update thread local
048: ThreadContext oldContext = threadStorage.get();
049: threadStorage.set(newContext);
050:
051: // notify listeners
052: for (ThreadContextListener listener : listeners) {
053: try {
054: listener.contextEntered(oldContext, newContext);
055: } catch (Throwable e) {
056: log.warning("ThreadContextListener threw an exception",
057: e);
058: }
059: }
060:
061: // return old context so it can be used for exit call below
062: return oldContext;
063: }
064:
065: public static void exit(ThreadContext oldContext) {
066: ThreadContext exitingContext = threadStorage.get();
067: if (exitingContext == null) {
068: throw new IllegalStateException("No existing context");
069: }
070:
071: // set the thread context class loader back
072: Thread.currentThread().setContextClassLoader(
073: exitingContext.oldClassLoader);
074: exitingContext.oldClassLoader = null;
075:
076: // update thread local
077: threadStorage.set(oldContext);
078:
079: // notify listeners
080: for (ThreadContextListener listener : listeners) {
081: try {
082: listener.contextExited(exitingContext, oldContext);
083: } catch (Throwable e) {
084: log
085: .debug(
086: "ThreadContextListener threw an exception",
087: e);
088: }
089: }
090: }
091:
092: public static void addThreadContextListener(
093: ThreadContextListener listener) {
094: listeners.add(listener);
095: }
096:
097: public static void removeThreadContextListener(
098: ThreadContextListener listener) {
099: listeners.remove(listener);
100: }
101:
102: private final CoreDeploymentInfo deploymentInfo;
103: private final Object primaryKey;
104: private final HashMap<Class, Object> data = new HashMap<Class, Object>();
105: private ClassLoader oldClassLoader;
106: private Operation currentOperation;
107: private BaseContext.State[] currentAllowedStates;
108: private Class invokedInterface;
109:
110: public ThreadContext(CoreDeploymentInfo deploymentInfo,
111: Object primaryKey) {
112: this (deploymentInfo, primaryKey, null);
113: }
114:
115: public ThreadContext(CoreDeploymentInfo deploymentInfo,
116: Object primaryKey, Operation operation) {
117: if (deploymentInfo == null) {
118: throw new NullPointerException("deploymentInfo is null");
119: }
120: this .deploymentInfo = deploymentInfo;
121: this .primaryKey = primaryKey;
122: this .currentOperation = operation;
123: }
124:
125: public ThreadContext(ThreadContext that) {
126: this .deploymentInfo = that.deploymentInfo;
127: this .primaryKey = that.primaryKey;
128: this .data.putAll(that.data);
129: this .oldClassLoader = that.oldClassLoader;
130: }
131:
132: public CoreDeploymentInfo getDeploymentInfo() {
133: return deploymentInfo;
134: }
135:
136: public Object getPrimaryKey() {
137: return primaryKey;
138: }
139:
140: public Operation getCurrentOperation() {
141: return currentOperation;
142: }
143:
144: public void setCurrentOperation(Operation operation) {
145: currentOperation = operation;
146: }
147:
148: public Class getInvokedInterface() {
149: return invokedInterface;
150: }
151:
152: public void setInvokedInterface(Class invokedInterface) {
153: this .invokedInterface = invokedInterface;
154: }
155:
156: public BaseContext.State[] getCurrentAllowedStates() {
157: return currentAllowedStates;
158: }
159:
160: public BaseContext.State[] setCurrentAllowedStates(
161: BaseContext.State[] newAllowedStates) {
162: BaseContext.State[] oldAllowedStates = currentAllowedStates;
163: currentAllowedStates = newAllowedStates;
164: return oldAllowedStates;
165: }
166:
167: @SuppressWarnings({"unchecked"})
168: public <T> T get(Class<T> type) {
169: return (T) data.get(type);
170: }
171:
172: @SuppressWarnings({"unchecked"})
173: public <T> T set(Class<T> type, T value) {
174: return (T) data.put(type, value);
175: }
176: }
|