You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2007/01/09 20:12:47 UTC

svn commit: r494528 - in /incubator/openejb/trunk/openejb3/container: ./ openejb-core/src/main/java/org/apache/openejb/alt/config/ openejb-core/src/main/java/org/apache/openejb/assembler/classic/ openejb-core/src/main/java/org/apache/openejb/core/ open...

Author: dain
Date: Tue Jan  9 11:12:46 2007
New Revision: 494528

URL: http://svn.apache.org/viewvc?view=rev&rev=494528
Log:
ThreadContext now uses enter and exit methods to demarc component boundries.
ThreadContext manages thead context class loader.
Added ThreadContextListener.

Added:
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContextListener.java
Modified:
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbJarInfoBuilder.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbModule.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContext.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityContainer.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityInstanceManager.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/BaseEjbProxyHandler.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/EncReference.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/java/javaURLContextFactory.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/SessionSynchronizationCoordinator.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessEjbHomeHandler.java
    incubator/openejb/trunk/openejb3/container/pom.xml

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbJarInfoBuilder.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbJarInfoBuilder.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbJarInfoBuilder.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbJarInfoBuilder.java Tue Jan  9 11:12:46 2007
@@ -74,6 +74,7 @@
 import java.util.Map;
 import java.util.Collections;
 import java.util.Iterator;
+import java.io.File;
 
 /**
  * @version $Revision$ $Date$
@@ -107,6 +108,7 @@
 
         EjbJarInfo ejbJar = new EjbJarInfo();
         ejbJar.jarPath = jar.getJarURI();
+        ejbJar.moduleId = new File(ejbJar.jarPath).getName().replaceFirst(".jar$","");
 
 
         for (EnterpriseBean bean : jar.getEjbJar().getEnterpriseBeans()) {

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbModule.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbModule.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbModule.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/alt/config/EjbModule.java Tue Jan  9 11:12:46 2007
@@ -29,12 +29,16 @@
  */
 public class EjbModule implements DeploymentModule {
 
-    private final ClassLoader classLoader;
+    private ClassLoader classLoader;
+    private final String jarURI;
     private final EjbJar ejbJar;
     private final OpenejbJar openejbJar;
-    private final String jarURI;
     private final String moduleId;
 
+    public EjbModule(String jarURI, EjbJar ejbJar, OpenejbJar openejbJar) {
+        this(null, jarURI, ejbJar, openejbJar);
+    }
+
     public EjbModule(ClassLoader classLoader, String jarURI, EjbJar ejbJar, OpenejbJar openejbJar) {
         this.classLoader = classLoader;
         this.ejbJar = ejbJar;
@@ -68,4 +72,7 @@
         return classLoader;
     }
 
+    public void setClassLoader(ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
 }

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java Tue Jan  9 11:12:46 2007
@@ -20,6 +20,7 @@
 import java.util.ArrayList;
 
 public class EjbJarInfo extends InfoObject {
+    public String moduleId;
     public String jarPath;
     public final List<EnterpriseBeanInfo> enterpriseBeans = new ArrayList<EnterpriseBeanInfo>();
     public final List<InterceptorInfo> defaultInterceptors = new ArrayList<InterceptorInfo>();

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContext.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContext.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContext.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContext.java Tue Jan  9 11:12:46 2007
@@ -17,124 +17,126 @@
 package org.apache.openejb.core;
 
 import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
-public class ThreadContext implements Cloneable {
+import org.apache.openejb.util.Logger;
 
-    protected static final ThreadLocal<ThreadContext> threadStorage = new ThreadLocal<ThreadContext>();
+public class ThreadContext {
+    private static final Logger log = Logger.getInstance("OpenEJB", "org.apache.openejb.util.resources");
+    private static final ThreadLocal<ThreadContext> threadStorage = new ThreadLocal<ThreadContext>();
+    private static final List<ThreadContextListener> listeners = new CopyOnWriteArrayList<ThreadContextListener>();
 
-    protected boolean valid = false;
-    protected CoreDeploymentInfo deploymentInfo;
-    protected Object primaryKey;
-    protected Operation currentOperation;
-    protected Object securityIdentity;
-    protected Object unspecified;
-    private final HashMap<Class, Object> data = new HashMap();
-
-    public <T> T get(Class<T> type) {
-        return (T)data.get(type);
+    public static ThreadContext getThreadContext() {
+        ThreadContext threadContext = threadStorage.get();
+        return threadContext;
     }
 
-    public <T> T set(Class<T> type, T value) {
-        return (T) data.put(type, value);
-    }
+    public static ThreadContext enter(ThreadContext newContext) {
+        if (newContext == null) {
+            throw new NullPointerException("newContext is null");
+        }
 
-    public static boolean isValid() {
-        ThreadContext tc = threadStorage.get();
-        if (tc != null)
-            return tc.valid;
-        else
-            return false;
-    }
-
-    protected void makeInvalid() {
-        valid = false;
-        deploymentInfo = null;
-        primaryKey = null;
-        currentOperation = null;
-        securityIdentity = null;
-        unspecified = null;
-        data.clear();
-    }
-
-    public static void invalidate() {
-        ThreadContext tc = threadStorage.get();
-        if (tc != null)
-            tc.makeInvalid();
-    }
-
-    public static void setThreadContext(ThreadContext tc) {
-        if (tc == null) {
-            tc = threadStorage.get();
-            if (tc != null) tc.makeInvalid();
-        } else {
-            threadStorage.set(tc);
+        // set the thread context class loader
+        newContext.oldClassLoader = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(newContext.deploymentInfo.getClassLoader());
+
+        // update thread local
+        ThreadContext oldContext = threadStorage.get();
+        threadStorage.set(newContext);
+
+        // notify listeners
+        for (ThreadContextListener listener : listeners) {
+            try {
+                listener.contextEntered(oldContext, newContext);
+            } catch (Throwable e) {
+                log.warning("ThreadContextListener threw an exception", e);
+            }
         }
+
+        // return old context so it can be used for exit call below
+        return oldContext;
     }
 
-    public static ThreadContext getThreadContext() {
-        ThreadContext tc = threadStorage.get();
-        if (tc == null) {
-            tc = new ThreadContext();
-            threadStorage.set(tc);
+    public static void exit(ThreadContext oldContext) {
+        ThreadContext exitingContext = threadStorage.get();
+        if (exitingContext == null) {
+            throw new IllegalStateException("No existing context");
         }
-        return tc;
-    }
 
-    public Operation getCurrentOperation() {
-        return currentOperation;
+        // set the thread context class loader back
+        Thread.currentThread().setContextClassLoader(exitingContext.oldClassLoader);
+        exitingContext.oldClassLoader = null;
+
+        // update thread local
+        threadStorage.set(oldContext);
+
+        // notify listeners
+        for (ThreadContextListener listener : listeners) {
+            try {
+                listener.contextExited(exitingContext, oldContext);
+            } catch (Throwable e) {
+                log.warning("ThreadContextListener threw an exception", e);
+            }
+        }
     }
 
-    public Object getPrimaryKey() {
-        return primaryKey;
+    public static void addThreadContextListener(ThreadContextListener listener) {
+        listeners.add(listener);
     }
 
-    public CoreDeploymentInfo getDeploymentInfo() {
-        return deploymentInfo;
+    public static void removeThreadContextListener(ThreadContextListener listener) {
+        listeners.remove(listener);
     }
 
-    public Object getSecurityIdentity() {
-        return securityIdentity;
-    }
+    private final CoreDeploymentInfo deploymentInfo;
+    private Object primaryKey;
+    private Operation currentOperation;
+    private final Object securityIdentity;
+    private final HashMap<Class, Object> data = new HashMap<Class, Object>();
+    private ClassLoader oldClassLoader;
 
-    public Object getUnspecified() {
-        return unspecified;
+    public ThreadContext(CoreDeploymentInfo deploymentInfo, Object primaryKey, Object securityIdentity) {
+        if (deploymentInfo == null) {
+            throw new NullPointerException("deploymentInfo is null");
+        }
+        this.deploymentInfo = deploymentInfo;
+        this.primaryKey = primaryKey;
+        this.securityIdentity = securityIdentity;
     }
 
-    public void set(CoreDeploymentInfo di, Object primKey, Object securityIdentity) {
-        setDeploymentInfo(di);
-        setPrimaryKey(primKey);
-        setSecurityIdentity(securityIdentity);
-        valid = true;
+    public CoreDeploymentInfo getDeploymentInfo() {
+        return deploymentInfo;
     }
 
-    public void setCurrentOperation(Operation op) {
-        currentOperation = op;
-        valid = true;
+    public Object getPrimaryKey() {
+        return primaryKey;
     }
 
     public void setPrimaryKey(Object primKey) {
         primaryKey = primKey;
-        valid = true;
     }
 
-    public void setSecurityIdentity(Object identity) {
-        securityIdentity = identity;
-        valid = true;
+    public Object getSecurityIdentity() {
+        return securityIdentity;
     }
 
-    public void setDeploymentInfo(CoreDeploymentInfo info) {
-        deploymentInfo = info;
+    public Operation getCurrentOperation() {
+        return currentOperation;
     }
 
-    public void setUnspecified(Object obj) {
-        unspecified = obj;
+    public void setCurrentOperation(Operation op) {
+        currentOperation = op;
     }
 
-    public boolean valid() {
-        return valid;
+    @SuppressWarnings({"unchecked"})
+    public <T> T get(Class<T> type) {
+        return (T)data.get(type);
     }
 
-    public java.lang.Object clone() throws java.lang.CloneNotSupportedException {
-        return super.clone();
+    @SuppressWarnings({"unchecked"})
+    public <T> T set(Class<T> type, T value) {
+        return (T) data.put(type, value);
     }
+
 }

Added: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContextListener.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContextListener.java?view=auto&rev=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContextListener.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ThreadContextListener.java Tue Jan  9 11:12:46 2007
@@ -0,0 +1,34 @@
+/**
+ *
+ * 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.openejb.core;
+
+public interface ThreadContextListener {
+    /**
+     * A new context has been entered.  The new context is already associated with the thread.
+     * @param oldContext the old context that was associated with the thread
+     * @param newContext the new context that is now associated with the thread
+     */
+    void contextEntered(ThreadContext oldContext, ThreadContext newContext);
+
+    /**
+     * A context has exited.  The reentered context is already associated with the thread.
+     * @param exitedContext the context that was exited
+     * @param reenteredContext the context that is not associated with the thread
+     */
+    void contextExited(ThreadContext exitedContext, ThreadContext reenteredContext);
+}

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java Tue Jan  9 11:12:46 2007
@@ -156,16 +156,14 @@
     public Object getEjbInstance(CoreDeploymentInfo deployInfo, Object primaryKey) {
         CmpEngine cmpEngine = getCmpEngine(deployInfo.getDeploymentID());
 
-        ThreadContext callContext = new ThreadContext();
-        callContext.setDeploymentInfo(deployInfo);
+        ThreadContext callContext = new ThreadContext(deployInfo, primaryKey, null);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
             Object bean = cmpEngine.loadBean(callContext, primaryKey);
             return bean;
         } finally {
-            ThreadContext.setThreadContext(oldCallContext);
+            ThreadContext.exit(oldCallContext);
         }
     }
 
@@ -198,13 +196,9 @@
 
     public Object invoke(Object deployID, Method callMethod, Object[] args, Object primKey, Object securityIdentity) throws OpenEJBException {
         CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) this.getDeploymentInfo(deployID);
-        ThreadContext callContext = new ThreadContext();
-        callContext.set(deployInfo, primKey, securityIdentity);
+        ThreadContext callContext = new ThreadContext(deployInfo, primKey, securityIdentity);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
-        ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
-        Thread.currentThread().setContextClassLoader(deployInfo.getClassLoader());
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
 
             boolean authorized = securityService.isCallerAuthorized(securityIdentity, deployInfo.getAuthorizedRoles(callMethod));
@@ -243,20 +237,7 @@
 
             return retValue;
         } finally {
-            /*
-                The thread context must be stripped from the thread before returning or throwing an exception
-                so that an object outside the container does not have access to a
-                bean's JNDI ENC.  In addition, its important for the
-                org.apache.openejb.core.ivm.java.javaURLContextFactory, which determines the context
-                of a JNDI lookup based on the presence of a ThreadContext object.  If no ThreadContext
-                object is available, then the request is assumed to be made from outside the container
-                system and is given the global OpenEJB JNDI name space instead.  If there is a thread context,
-                then the request is assumed to be made from within the container system and so the
-                javaContextFactory must return the JNDI ENC of the current enterprise bean which it
-                obtains from the DeploymentInfo object associated with the current thread context.
-            */
-            ThreadContext.setThreadContext(oldCallContext);
-            Thread.currentThread().setContextClassLoader(oldCL);
+            ThreadContext.exit(oldCallContext);
         }
     }
 
@@ -280,8 +261,7 @@
         KeyGenerator keyGenerator = deployInfo.getKeyGenerator();
         Object primaryKey = keyGenerator.getPrimaryKey(entityBean);
 
-        ThreadContext callContext = new ThreadContext();
-        callContext.set(deployInfo, primaryKey, null);
+        ThreadContext callContext = new ThreadContext(deployInfo, primaryKey, null);
         return callContext;
     }
 
@@ -291,18 +271,16 @@
         // activating entity doen't have a primary key
         CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) getDeploymentInfoByClass(entityBean.getClass());
 
-        ThreadContext callContext = new ThreadContext();
-        callContext.setDeploymentInfo(deployInfo);
+        ThreadContext callContext = new ThreadContext(deployInfo, null, null);
         callContext.setCurrentOperation(Operation.OP_SET_CONTEXT);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
             entityBean.setEntityContext(new EntityContext(transactionManager, securityService));
         } catch (RemoteException e) {
             throw new EJBException(e);
         } finally {
-            ThreadContext.setThreadContext(oldCallContext);
+            ThreadContext.exit(oldCallContext);
         }
     }
 
@@ -312,14 +290,13 @@
         ThreadContext callContext = createThreadContext(entityBean);
         callContext.setCurrentOperation(Operation.OP_UNSET_CONTEXT);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
             entityBean.unsetEntityContext();
         } catch (RemoteException e) {
             throw new EJBException(e);
         } finally {
-            ThreadContext.setThreadContext(oldCallContext);
+            ThreadContext.exit(oldCallContext);
         }
     }
 
@@ -329,14 +306,13 @@
         ThreadContext callContext = createThreadContext(entityBean);
         callContext.setCurrentOperation(Operation.OP_LOAD);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
             entityBean.ejbLoad();
         } catch (RemoteException e) {
             throw new EJBException(e);
         } finally {
-            ThreadContext.setThreadContext(oldCallContext);
+            ThreadContext.exit(oldCallContext);
         }
     }
 
@@ -346,14 +322,13 @@
         ThreadContext callContext = createThreadContext(entityBean);
         callContext.setCurrentOperation(Operation.OP_STORE);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
             entityBean.ejbStore();
         } catch (RemoteException e) {
             throw new EJBException(e);
         } finally {
-            ThreadContext.setThreadContext(oldCallContext);
+            ThreadContext.exit(oldCallContext);
         }
     }
 
@@ -364,8 +339,7 @@
         ThreadContext callContext = createThreadContext(entityBean);
         callContext.setCurrentOperation(Operation.OP_REMOVE);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
             entityBean.ejbRemove();
         } catch (RemoteException e) {
@@ -377,7 +351,7 @@
                 entityBean.getClass().getMethod("OpenEJB_deleted").invoke(entityBean);
             } catch (Exception ignored) {
             }
-            ThreadContext.setThreadContext(oldCallContext);
+            ThreadContext.exit(oldCallContext);
         }
     }
 
@@ -397,18 +371,16 @@
         // activating entity doen't have a primary key
         CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) getDeploymentInfoByClass(entityBean.getClass());
 
-        ThreadContext callContext = new ThreadContext();
-        callContext.setDeploymentInfo(deployInfo);
+        ThreadContext callContext = createThreadContext(entityBean);
         callContext.setCurrentOperation(Operation.OP_ACTIVATE);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
             entityBean.ejbActivate();
         } catch (RemoteException e) {
             throw new EJBException(e);
         } finally {
-            ThreadContext.setThreadContext(oldCallContext);
+            ThreadContext.exit(oldCallContext);
         }
     }
 
@@ -418,14 +390,13 @@
         ThreadContext callContext = createThreadContext(entityBean);
         callContext.setCurrentOperation(Operation.OP_PASSIVATE);
 
-        ThreadContext oldCallContext = ThreadContext.getThreadContext();
-        ThreadContext.setThreadContext(callContext);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
             entityBean.ejbPassivate();
         } catch (RemoteException e) {
             throw new EJBException(e);
         } finally {
-            ThreadContext.setThreadContext(oldCallContext);
+            ThreadContext.exit(oldCallContext);
         }
     }
 

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityContainer.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityContainer.java Tue Jan  9 11:12:46 2007
@@ -37,6 +37,7 @@
 import org.apache.openejb.spi.SecurityService;
 import org.apache.openejb.core.Operation;
 import org.apache.openejb.core.ThreadContext;
+import org.apache.openejb.core.CoreDeploymentInfo;
 import org.apache.openejb.core.transaction.TransactionContainer;
 import org.apache.openejb.core.transaction.TransactionContext;
 import org.apache.openejb.core.transaction.TransactionPolicy;
@@ -91,13 +92,10 @@
     }
 
     public Object invoke(Object deployID, Method callMethod, Object [] args, Object primKey, Object securityIdentity) throws org.apache.openejb.OpenEJBException {
+        CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) this.getDeploymentInfo(deployID);
+        ThreadContext callContext = new ThreadContext(deployInfo, primKey, securityIdentity);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
-
-            org.apache.openejb.core.CoreDeploymentInfo deployInfo = (org.apache.openejb.core.CoreDeploymentInfo) this.getDeploymentInfo(deployID);
-
-            ThreadContext callContext = ThreadContext.getThreadContext();
-            callContext.set(deployInfo, primKey, securityIdentity);
-
             boolean authorized = getSecurityService().isCallerAuthorized(securityIdentity, deployInfo.getAuthorizedRoles(callMethod));
             if (!authorized)
                 throw new org.apache.openejb.ApplicationException(new RemoteException("Unauthorized Access by Principal Denied"));
@@ -134,19 +132,7 @@
             return retValue;
 
         } finally {
-            /*
-                The thread context must be stripped from the thread before returning or throwing an exception
-                so that an object outside the container does not have access to a
-                bean's JNDI ENC.  In addition, its important for the
-                org.apache.openejb.core.ivm.java.javaURLContextFactory, which determines the context
-                of a JNDI lookup based on the presence of a ThreadContext object.  If no ThreadContext
-                object is available, then the request is assumed to be made from outside the container
-                system and is given the global OpenEJB JNDI name space instead.  If there is a thread context,
-                then the request is assumed to be made from within the container system and so the
-                javaContextFactory must return the JNDI ENC of the current enterprise bean which it
-                obtains from the DeploymentInfo object associated with the current thread context.
-            */
-            ThreadContext.setThreadContext(null);
+            ThreadContext.exit(oldCallContext);
         }
     }
 

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityInstanceManager.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityInstanceManager.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityInstanceManager.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/entity/EntityInstanceManager.java Tue Jan  9 11:12:46 2007
@@ -30,6 +30,8 @@
 import javax.ejb.EntityBean;
 import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
 import java.util.HashMap;
 import java.util.Hashtable;
 
@@ -517,8 +519,7 @@
     * to the method ready pool. Instances of this class are not recycled anymore, because modern VMs
     * (JDK1.3 and above) perform better for objects that are short lived.
     */
-    protected class SyncronizationWrapper
-            implements javax.transaction.Synchronization {
+    protected class SyncronizationWrapper implements Synchronization {
         private EntityBean bean;
         /*
         * <tt>isAvailable<tt> determines if the wrapper is still associated with a bean.  If the bean identity is removed (ejbRemove)
@@ -527,23 +528,22 @@
         */
         private boolean isAvailable;
         private boolean isAssociated;
-        private final ThreadContext context;
         private final Key myIndex;
+        private final CoreDeploymentInfo deploymentInfo;
+        private final Object primaryKey;
+        private final Object securityIdentity;
 
-        public SyncronizationWrapper(EntityBean ebean, Key key, boolean available, ThreadContext ctx) throws OpenEJBException {
-            if (ebean == null || ctx == null || key == null) {
+        public SyncronizationWrapper(EntityBean bean, Key key, boolean available, ThreadContext callContext) throws OpenEJBException {
+            if (bean == null || callContext == null || key == null) {
                 throw new IllegalArgumentException();
             }
-            bean = ebean;
+            this.bean = bean;
             isAvailable = available;
             myIndex = key;
             isAssociated = true;
-            try {
-                context = (ThreadContext) ctx.clone();
-            } catch (CloneNotSupportedException e) {
-                logger.error("Thread context class " + ctx.getClass() + " doesn't implement the Cloneable interface!", e);
-                throw new OpenEJBException("Thread context class " + ctx.getClass() + " doesn't implement the Cloneable interface!");
-            }
+            deploymentInfo = callContext.getDeploymentInfo();
+            primaryKey = callContext.getPrimaryKey();
+            securityIdentity = callContext.getSecurityIdentity();
         }
 
         public void disassociate() {
@@ -558,37 +558,41 @@
             return isAvailable;
         }
 
-        public void setEntityBean(EntityBean ebean) {
+        public synchronized void setEntityBean(EntityBean ebean) {
             isAvailable = true;
             bean = ebean;
         }
 
-        public EntityBean getEntityBean() {
+        public synchronized EntityBean getEntityBean() {
             isAvailable = false;
             return bean;
         }
 
         public void beforeCompletion() {
             if (isAssociated) {
+                EntityBean bean;
+                synchronized (this) {
+                    bean = this.bean;
+                }
+
+                ThreadContext callContext = new ThreadContext(deploymentInfo, primaryKey, securityIdentity);
+                callContext.setCurrentOperation(Operation.OP_STORE);
+
+                ThreadContext oldCallContext = ThreadContext.enter(callContext);
 
-                ThreadContext currentContext = ThreadContext.getThreadContext();
-                ThreadContext.setThreadContext(context);
-                Operation orginalOperation = context.getCurrentOperation();
-                context.setCurrentOperation(org.apache.openejb.core.Operation.OP_STORE);
                 try {
                     bean.ejbStore();
                 } catch (Exception re) {
                     logger.error("Exception occured during ejbStore()", re);
-                    javax.transaction.TransactionManager txmgr = getTransactionManager();
+                    TransactionManager transactionManager = getTransactionManager();
                     try {
-                        txmgr.setRollbackOnly();
-                    } catch (javax.transaction.SystemException se) {
+                        transactionManager.setRollbackOnly();
+                    } catch (SystemException se) {
                         logger.error("Transaction manager reported error during setRollbackOnly()", se);
                     }
 
                 } finally {
-
-                    ThreadContext.setThreadContext(currentContext);
+                    ThreadContext.exit(oldCallContext);
                 }
             }
         }
@@ -596,7 +600,6 @@
         public void afterCompletion(int status) {
             txReadyPool.remove(myIndex);
         }
-
     }
 }
 

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/BaseEjbProxyHandler.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/BaseEjbProxyHandler.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/BaseEjbProxyHandler.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/BaseEjbProxyHandler.java Tue Jan  9 11:12:46 2007
@@ -113,7 +113,7 @@
 
     protected Object getThreadSpecificSecurityIdentity() {
         ThreadContext context = ThreadContext.getThreadContext();
-        if (context.valid()) {
+        if (context != null) {
             return context.getSecurityIdentity();
         } else {
             return getSecurityService().getSecurityIdentity();
@@ -142,33 +142,33 @@
             else
                 throw new UnsupportedOperationException("Unkown method: " + method);
         }
-        /* Preserve the context
-            When entering a container the ThreadContext will change to match the context of
-            the bean being serviced. That changes the current context of the calling bean,
-            so the context must be preserved and then resourced after request is serviced.
-            The context is restored in the finnaly clause below.
-
-            We could have same some typing by obtaining a ref to the ThreadContext and then
-            setting the current ThreadContext to null, but this results in more object creation
-            since the container will create a new context on the invoke( ) operation if the current
-            context is null. Getting the context values and resetting them reduces object creation.
-            It's ugly but performant.
-        */
-
-        ThreadContext cntext = null;
-        CoreDeploymentInfo depInfo = null;
-        Object prmryKey = null;
-        Operation crrntOperation = null;
-        Object scrtyIdentity = null;
-        boolean cntextValid = false;
-        cntext = ThreadContext.getThreadContext();
-        if (cntext.valid()) {
-            depInfo = cntext.getDeploymentInfo();
-            prmryKey = cntext.getPrimaryKey();
-            crrntOperation = cntext.getCurrentOperation();
-            scrtyIdentity = cntext.getSecurityIdentity();
-            cntextValid = true;
-        }
+//        /* Preserve the context
+//            When entering a container the ThreadContext will change to match the context of
+//            the bean being serviced. That changes the current context of the calling bean,
+//            so the context must be preserved and then resourced after request is serviced.
+//            The context is restored in the finnaly clause below.
+//
+//            We could have same some typing by obtaining a ref to the ThreadContext and then
+//            setting the current ThreadContext to null, but this results in more object creation
+//            since the container will create a new context on the invoke( ) operation if the current
+//            context is null. Getting the context values and resetting them reduces object creation.
+//            It's ugly but performant.
+//        */
+//
+//        ThreadContext cntext = null;
+//        CoreDeploymentInfo depInfo = null;
+//        Object prmryKey = null;
+//        Operation crrntOperation = null;
+//        Object scrtyIdentity = null;
+//        boolean cntextValid = false;
+//        cntext = ThreadContext.getThreadContext();
+//        if (cntext.valid()) {
+//            depInfo = cntext.getDeploymentInfo();
+//            prmryKey = cntext.getPrimaryKey();
+//            crrntOperation = cntext.getCurrentOperation();
+//            scrtyIdentity = cntext.getSecurityIdentity();
+//            cntextValid = true;
+//        }
 
         String jndiEnc = System.getProperty(javax.naming.Context.URL_PKG_PREFIXES);
 //        System.setProperty(javax.naming.Context.URL_PKG_PREFIXES,"org.apache.openejb.core.ivm.naming");
@@ -230,10 +230,10 @@
         } finally {
 //            System.setProperty(javax.naming.Context.URL_PKG_PREFIXES, jndiEnc);
 
-            if (cntextValid) {
-                cntext.set(depInfo, prmryKey, scrtyIdentity);
-                cntext.setCurrentOperation(crrntOperation);
-            }
+//            if (cntextValid) {
+//                cntext.set(depInfo, prmryKey, scrtyIdentity);
+//                cntext.setCurrentOperation(crrntOperation);
+//            }
             if (doIntraVmCopy == true) {
 
                 IntraVmCopyMonitor.postCopyOperation();

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java Tue Jan  9 11:12:46 2007
@@ -275,7 +275,7 @@
             stub = null;
         }
 
-        container.invoke(deploymentID, method, args, primKey, ThreadContext.getThreadContext().getSecurityIdentity());
+        container.invoke(deploymentID, method, args, primKey, getThreadSpecificSecurityIdentity());
 
         /*
          * This operation takes care of invalidating all the EjbObjectProxyHanders associated with

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/EncReference.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/EncReference.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/EncReference.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/EncReference.java Tue Jan  9 11:12:46 2007
@@ -47,9 +47,9 @@
     * Obtains the referenced object.
     */
     public Object getObject() throws javax.naming.NamingException {
-        if (ThreadContext.isValid()) {
-            ThreadContext cntx = ThreadContext.getThreadContext();
-            checkOperation(cntx.getCurrentOperation());
+        ThreadContext callContext = ThreadContext.getThreadContext();
+        if (callContext != null) {
+            checkOperation(callContext.getCurrentOperation());
         }
         return ref.getObject();
     }

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/java/javaURLContextFactory.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/java/javaURLContextFactory.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/java/javaURLContextFactory.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/java/javaURLContextFactory.java Tue Jan  9 11:12:46 2007
@@ -66,12 +66,13 @@
     public Context getContext() {
         Context jndiCtx = null;
 
-        if (!ThreadContext.isValid()) {
+        ThreadContext callContext = ThreadContext.getThreadContext();
+        if (callContext == null) {
             ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
             return containerSystem.getJNDIContext();
         }
 
-        CoreDeploymentInfo di = ThreadContext.getThreadContext().getDeploymentInfo();
+        CoreDeploymentInfo di = callContext.getDeploymentInfo();
         if (di != null) {
             return di.getJndiEnc();
         } else {

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java Tue Jan  9 11:12:46 2007
@@ -163,29 +163,28 @@
         if (deployInfo == null) throw new SystemException("Unknown deployment " + deployId);
 
         // intialize call context
-        ThreadContext callContext = ThreadContext.getThreadContext();
-        callContext.setDeploymentInfo(deployInfo);
+        ThreadContext callContext = new ThreadContext(deployInfo, null, null);
+        ThreadContext oldContext = ThreadContext.enter(callContext);
+
+        // create mdb context
         MdbCallContext mdbCallContext = new MdbCallContext();
-        callContext.setUnspecified(mdbCallContext);
+        callContext.set(MdbCallContext.class, mdbCallContext);
         mdbCallContext.deliveryMethod = method;
+        mdbCallContext.oldCallContext = oldContext;
 
-        // create the tx data
+        // add tx data
         mdbCallContext.txPolicy = deployInfo.getTransactionPolicy(method);
         mdbCallContext.txContext = new TransactionContext(callContext, transactionManager);
 
-        // install the application classloader
-        installAppClassLoader(mdbCallContext, deployInfo.getClassLoader());
-
         // call the tx before method
         try {
             mdbCallContext.txPolicy.beforeInvoke(instance, mdbCallContext.txContext);
             enlistResource(xaResource);
         } catch (ApplicationException e) {
-            restoreAdapterClassLoader(mdbCallContext);
-
+            ThreadContext.exit(oldContext);
             throw new SystemException("Should never get an Application exception", e);
         } catch (SystemException e) {
-            restoreAdapterClassLoader(mdbCallContext);
+            ThreadContext.exit(oldContext);
             throw e;
         }
     }
@@ -211,7 +210,7 @@
         // get the context data
         ThreadContext callContext = ThreadContext.getThreadContext();
         CoreDeploymentInfo deployInfo = callContext.getDeploymentInfo();
-        MdbCallContext mdbCallContext = (MdbCallContext) callContext.getUnspecified();
+        MdbCallContext mdbCallContext = callContext.get(MdbCallContext.class);
 
         if (mdbCallContext == null) {
             throw new IllegalStateException("beforeDelivery was not called");
@@ -286,8 +285,7 @@
     public void afterDelivery(Object instance) throws SystemException {
         // get the mdb call context
         ThreadContext callContext = ThreadContext.getThreadContext();
-        MdbCallContext mdbCallContext = (MdbCallContext) callContext.getUnspecified();
-        ThreadContext.setThreadContext(null);
+        MdbCallContext mdbCallContext = callContext.get(MdbCallContext.class);
 
         // invoke the tx after method
         try {
@@ -295,15 +293,14 @@
         } catch (ApplicationException e) {
             throw new SystemException("Should never get an Application exception", e);
         } finally {
-            restoreAdapterClassLoader(mdbCallContext);
+            ThreadContext.exit(mdbCallContext.oldCallContext);
         }
     }
 
     public void release(Object instance) {
         // get the mdb call context
         ThreadContext callContext = ThreadContext.getThreadContext();
-        MdbCallContext mdbCallContext = (MdbCallContext) callContext.getUnspecified();
-        ThreadContext.setThreadContext(null);
+        MdbCallContext mdbCallContext = callContext.get(MdbCallContext.class);
 
         // if we have an mdb call context we need to invoke the after invoke method
         if (mdbCallContext != null) {
@@ -312,7 +309,7 @@
             } catch (Exception e) {
                 logger.error("error while releasing message endpoint", e);
             } finally {
-                restoreAdapterClassLoader(mdbCallContext);
+                ThreadContext.exit(mdbCallContext.oldCallContext);
             }
         }
     }
@@ -320,23 +317,9 @@
 
     private static class MdbCallContext {
         private Method deliveryMethod;
-        private ClassLoader adapterClassLoader;
         private TransactionPolicy txPolicy;
         private TransactionContext txContext;
-    }
-
-    private void installAppClassLoader(MdbCallContext mdbCallContext, ClassLoader applicationClassLoader) {
-        Thread currentThread = Thread.currentThread();
-
-        mdbCallContext.adapterClassLoader = currentThread.getContextClassLoader();
-        if (mdbCallContext.adapterClassLoader != applicationClassLoader) {
-            currentThread.setContextClassLoader(applicationClassLoader);
-        }
-    }
-
-    private void restoreAdapterClassLoader(MdbCallContext mdbCallContext) {
-        Thread.currentThread().setContextClassLoader(mdbCallContext.adapterClassLoader);
-        mdbCallContext.adapterClassLoader = null;
+        private ThreadContext oldCallContext;
     }
 
     public void discardInstance(Object instance, ThreadContext context) {

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/SessionSynchronizationCoordinator.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/SessionSynchronizationCoordinator.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/SessionSynchronizationCoordinator.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/SessionSynchronizationCoordinator.java Tue Jan  9 11:12:46 2007
@@ -23,19 +23,19 @@
 import org.apache.openejb.core.transaction.TransactionContext;
 import org.apache.openejb.util.Logger;
 
-import javax.ejb.EnterpriseBean;
 import javax.ejb.SessionSynchronization;
 import javax.transaction.Status;
 import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 import java.util.HashMap;
+import java.util.Map;
 
 public class SessionSynchronizationCoordinator implements javax.transaction.Synchronization {
+    private static Logger logger = Logger.getInstance("OpenEJB", "org.apache.openejb.util.resources");
 
-    private static java.util.HashMap coordinators = new java.util.HashMap();
-    public static Logger logger = Logger.getInstance("OpenEJB", "org.apache.openejb.util.resources");
+    private static Map<Transaction,SessionSynchronizationCoordinator> coordinators = new HashMap<Transaction,SessionSynchronizationCoordinator>();
 
-    private final HashMap sessionSynchronizations = new java.util.HashMap();
+    private final Map<Object,ThreadContext> sessionSynchronizations = new HashMap<Object,ThreadContext>();
     private final TransactionManager transactionManager;
 
     private SessionSynchronizationCoordinator(TransactionManager transactionManager) {
@@ -45,13 +45,14 @@
     public static void registerSessionSynchronization(SessionSynchronization session, TransactionContext context) throws javax.transaction.SystemException, javax.transaction.RollbackException {
         SessionSynchronizationCoordinator coordinator = null;
 
-        coordinator = (SessionSynchronizationCoordinator) coordinators.get(context.currentTx);
+        coordinator = coordinators.get(context.currentTx);
 
         if (coordinator == null) {
             coordinator = new SessionSynchronizationCoordinator(context.getTransactionManager());
             try {
                 context.currentTx.registerSynchronization(coordinator);
             } catch (Exception e) {
+                // todo this seems bad...
                 logger.error("Transaction.registerSynchronization failed.", e);
                 return;
             }
@@ -67,7 +68,7 @@
         if (registered) return;
 
         try {
-            callContext = (ThreadContext) callContext.clone();
+            callContext = new ThreadContext(callContext.getDeploymentInfo(), callContext.getPrimaryKey(), callContext.getSecurityIdentity());
         } catch (Exception e) {
         }
         sessionSynchronizations.put(callContext.getPrimaryKey(), callContext);
@@ -90,15 +91,13 @@
 
     public void beforeCompletion() {
 
-        ThreadContext originalContext = ThreadContext.getThreadContext();
-
         Object[] contexts = sessionSynchronizations.values().toArray();
 
         for (int i = 0; i < contexts.length; i++) {
 
             ThreadContext callContext = (ThreadContext) contexts[i];
 
-            ThreadContext.setThreadContext(callContext);
+            ThreadContext oldCallContext = ThreadContext.enter(callContext);
             StatefulInstanceManager instanceManager = null;
 
             try {
@@ -112,7 +111,7 @@
 
                 SessionSynchronization bean = (SessionSynchronization) instanceManager.obtainInstance(callContext.getPrimaryKey(), callContext);
                 bean.beforeCompletion();
-                instanceManager.poolInstance(callContext.getPrimaryKey(), (EnterpriseBean) bean);
+                instanceManager.poolInstance(callContext.getPrimaryKey(), bean);
             } catch (org.apache.openejb.InvalidateReferenceException inv) {
 
             } catch (Exception e) {
@@ -141,15 +140,13 @@
                 /* [4] throw the java.rmi.RemoteException to the client */
                 throw new RuntimeException(message);
             } finally {
-                ThreadContext.setThreadContext(originalContext);
+                ThreadContext.exit(oldCallContext);
             }
         }
     }
 
     public void afterCompletion(int status) {
 
-        ThreadContext originalContext = ThreadContext.getThreadContext();
-
         Object[] contexts = sessionSynchronizations.values().toArray();
 
         try {
@@ -162,7 +159,7 @@
 
             ThreadContext callContext = (ThreadContext) contexts[i];
 
-            ThreadContext.setThreadContext(callContext);
+            ThreadContext oldCallContext = ThreadContext.enter(callContext);
             StatefulInstanceManager instanceManager = null;
 
             try {
@@ -177,7 +174,7 @@
                 SessionSynchronization bean = (SessionSynchronization) instanceManager.obtainInstance(callContext.getPrimaryKey(), callContext);
 
                 bean.afterCompletion(status == Status.STATUS_COMMITTED);
-                instanceManager.poolInstance(callContext.getPrimaryKey(), (EnterpriseBean) bean);
+                instanceManager.poolInstance(callContext.getPrimaryKey(), bean);
             } catch (org.apache.openejb.InvalidateReferenceException inv) {
 
             } catch (Exception e) {
@@ -208,7 +205,7 @@
 
                 throw new RuntimeException(message);
             } finally {
-                ThreadContext.setThreadContext(originalContext);
+                ThreadContext.exit(oldCallContext);
             }
         }
     }

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java Tue Jan  9 11:12:46 2007
@@ -195,13 +195,10 @@
     }
 
     public Object invoke(Object deployID, Method callMethod, Object [] args, Object primKey, Object securityIdentity) throws org.apache.openejb.OpenEJBException {
+        CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) this.getDeploymentInfo(deployID);
+        ThreadContext callContext = new ThreadContext(deployInfo, primKey, securityIdentity);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
-
-            CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) this.getDeploymentInfo(deployID);
-
-            ThreadContext callContext = ThreadContext.getThreadContext();
-            callContext.set(deployInfo, primKey, securityIdentity);
-
             boolean authorized = getSecurityService().isCallerAuthorized(securityIdentity, deployInfo.getAuthorizedRoles(callMethod));
 
             if (!authorized){
@@ -229,21 +226,8 @@
             return returnValue;
 
         } finally {
-            /*
-                The thread context must be stripped from the thread before returning or throwing an exception
-                so that an object outside the container does not have access to a
-                bean's JNDI ENC.  In addition, its important for the
-                org.apache.openejb.core.ivm.java.javaURLContextFactory, which determines the context
-                of a JNDI lookup based on the presence of a ThreadContext object.  If no ThreadContext
-                object is available, then the request is assumed to be made from outside the container
-                system and is given the global OpenEJB JNDI name space instead.  If there is a thread context,
-                then the request is assumed to be made from within the container system and so the
-                javaContextFactory must return the JNDI ENC of the current enterprise bean which it
-                obtains from the DeploymentInfo object associated with the current thread context.
-            */
-            ThreadContext.setThreadContext(null);
+            ThreadContext.exit(oldCallContext);
         }
-
     }
 
     private SecurityService getSecurityService() {
@@ -327,9 +311,8 @@
 
     }
 
-    protected ProxyInfo createEJBObject(Method callMethod, Object [] args, ThreadContext callContext)
-            throws org.apache.openejb.OpenEJBException {
-        CoreDeploymentInfo deploymentInfo = (CoreDeploymentInfo) callContext.getDeploymentInfo();
+    protected ProxyInfo createEJBObject(Method callMethod, Object [] args, ThreadContext callContext) throws OpenEJBException {
+        CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
         Class beanType = deploymentInfo.getBeanClass();
         Object primaryKey = this.newPrimaryKey();
         callContext.setPrimaryKey(primaryKey);

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java Tue Jan  9 11:12:46 2007
@@ -22,6 +22,7 @@
 import org.apache.openejb.ProxyInfo;
 import org.apache.openejb.core.Operation;
 import org.apache.openejb.core.ThreadContext;
+import org.apache.openejb.core.CoreDeploymentInfo;
 import org.apache.openejb.core.transaction.TransactionContainer;
 import org.apache.openejb.core.transaction.TransactionContext;
 import org.apache.openejb.core.transaction.TransactionPolicy;
@@ -87,15 +88,11 @@
         di.setContainer(this);
     }
 
-    public Object invoke(Object deployID, Method callMethod, Object [] args, Object primKey, Object securityIdentity)
-            throws org.apache.openejb.OpenEJBException {
+    public Object invoke(Object deployID, Method callMethod, Object [] args, Object primKey, Object securityIdentity) throws OpenEJBException {
+        CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) this.getDeploymentInfo(deployID);
+        ThreadContext callContext = new ThreadContext(deployInfo, primKey, securityIdentity);
+        ThreadContext oldCallContext = ThreadContext.enter(callContext);
         try {
-
-            org.apache.openejb.core.CoreDeploymentInfo deployInfo = (org.apache.openejb.core.CoreDeploymentInfo) this.getDeploymentInfo(deployID);
-
-            ThreadContext callContext = ThreadContext.getThreadContext();
-            callContext.set(deployInfo, primKey, securityIdentity);
-
             boolean authorized = getSecurityService().isCallerAuthorized(securityIdentity, deployInfo.getAuthorizedRoles(callMethod));
             if (!authorized)
                 throw new org.apache.openejb.ApplicationException(new RemoteException("Unauthorized Access by Principal Denied"));
@@ -122,19 +119,7 @@
             return retValue;
 
         } finally {
-            /*
-                The thread context must be stripped from the thread before returning or throwing an exception
-                so that an object outside the container does not have access to a
-                bean's JNDI ENC.  In addition, its important for the
-                org.apache.openejb.core.ivm.java.javaURLContextFactory, which determines the context
-                of a JNDI lookup based on the presence of a ThreadContext object.  If no ThreadContext
-                object is available, then the request is assumed to be made from outside the container
-                system and is given the global OpenEJB JNDI name space instead.  If there is a thread context,
-                then the request is assumed to be made from within the container system and so the
-                javaContextFactory must return the JNDI ENC of the current enterprise bean which it
-                obtains from the DeploymentInfo object associated with the current thread context.
-            */
-            ThreadContext.setThreadContext(null);
+            ThreadContext.exit(oldCallContext);
         }
     }
 

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessEjbHomeHandler.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessEjbHomeHandler.java?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessEjbHomeHandler.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessEjbHomeHandler.java Tue Jan  9 11:12:46 2007
@@ -22,7 +22,6 @@
 
 import org.apache.openejb.InterfaceType;
 import org.apache.openejb.RpcContainer;
-import org.apache.openejb.core.ThreadContext;
 import org.apache.openejb.core.ivm.EjbHomeProxyHandler;
 import org.apache.openejb.core.ivm.EjbObjectProxyHandler;
 import org.apache.openejb.core.ivm.IntraVmHandle;
@@ -61,7 +60,7 @@
             stub = null;
         }
 
-        container.invoke(deploymentID, method, args, primKey, ThreadContext.getThreadContext().getSecurityIdentity());
+        container.invoke(deploymentID, method, args, primKey, getThreadSpecificSecurityIdentity());
         if (stub != null) {
             stub.invalidateReference();
         }

Modified: incubator/openejb/trunk/openejb3/container/pom.xml
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/pom.xml?view=diff&rev=494528&r1=494527&r2=494528
==============================================================================
--- incubator/openejb/trunk/openejb3/container/pom.xml (original)
+++ incubator/openejb/trunk/openejb3/container/pom.xml Tue Jan  9 11:12:46 2007
@@ -33,5 +33,6 @@
     <module>openejb-javaagent</module>
     <module>openejb-jee</module>
     <module>openejb-persistence</module>
+    <module>openejb-builder</module>
   </modules>
 </project>