Author: rmannibucau
Date: Mon May 28 17:55:19 2012
New Revision: 1343340
URL: http://svn.apache.org/viewvc?rev=1343340&view=rev
Log:
TOMEE-199 using the classloader too to match the webbeancontext
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java
Modified:
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java?rev=1343340&r1=1343339&r2=1343340&view=diff
==============================================================================
---
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java
(original)
+++
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java
Mon May 28 17:55:19 2012
@@ -18,10 +18,12 @@
package org.apache.openejb.cdi;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.openejb.AppContext;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.EjbJarInfo;
+import org.apache.openejb.core.WebContext;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.spi.ContainerSystem;
import org.apache.openejb.util.LogCategory;
@@ -57,14 +59,13 @@ public class ThreadSingletonServiceImpl
public static final Logger logger =
Logger.getInstance(LogCategory.OPENEJB_STARTUP,
ThreadSingletonServiceImpl.class);
//this needs to be static because OWB won't tell us what the existing
SingletonService is and you can't set it twice.
private static final ThreadLocal<WebBeansContext> contexts = new
ThreadLocal<WebBeansContext>();
+ private static final Map<ClassLoader, WebBeansContext>
contextByClassLoader = new ConcurrentHashMap<ClassLoader, WebBeansContext>();
private static final String WEBBEANS_FAILOVER_ISSUPPORTFAILOVER =
"org.apache.webbeans.web.failover.issupportfailover";
public ThreadSingletonServiceImpl() {
// no-op
}
-
-
@Override
public void initialize(StartupObject startupObject) {
AppContext appContext = startupObject.getAppContext();
@@ -189,6 +190,9 @@ public class ThreadSingletonServiceImpl
}
private static void contextMessage(WebBeansContext newOWBContext, String
prefix) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(prefix + "'" + newOWBContext + "'");
+ }
}
@Override
@@ -201,24 +205,65 @@ public class ThreadSingletonServiceImpl
contexts.set((WebBeansContext) oldContext);
}
- private WebBeansContext getContext() {
- return get();
+ private WebBeansContext getContext(final ClassLoader cl) {
+ return get(cl);
}
- public static WebBeansContext get()
- {
- WebBeansContext context = contexts.get();
- if (context == null) {
- // Fallback strategy is to just grab the first AppContext and
assume it is the right one
- // This kind of algorithm could be greatly improved
- final ContainerSystem containerSystem =
SystemInstance.get().getComponent(ContainerSystem.class);
+ /**
+ * Generally contexts.get() is enough since we set the current context
from a request (see webbeanslistener)
+ * but sometimes matching the classloader is better (manager webapps of
tomcat deploys for instance)
+ * so here the algorithm:
+ * 1) try to match with the classloader
+ * 2) if not matched try to use the threadlocal
+ * 3) (shouldn't happen) simply return the biggest webbeancontext
+ *
+ * @param cl the key (generally TCCL)
+ * @return the webbeancontext matching the current context
+ */
+ public static WebBeansContext get(final ClassLoader cl) {
+ WebBeansContext context = contextByClassLoader.get(cl);
+ if (context != null) {
+ return context;
+ }
- final List<AppContext> appContexts =
containerSystem.getAppContexts();
+ final ContainerSystem containerSystem =
SystemInstance.get().getComponent(ContainerSystem.class);
+ for (AppContext appContext : containerSystem.getAppContexts()) {
+ if (appContext.getClassLoader().equals(cl)) {
+ context = appContext.getWebBeansContext();
+ break;
+ }
+ for (WebContext web : appContext.getWebContexts()) {
+ if (web.getClassLoader().equals(cl)) {
+ if (web.getWebbeansContext() != null) { // ear
+ context = web.getWebbeansContext();
+ break;
+ } else { // war
+ context = appContext.getWebBeansContext();
+ break;
+ }
+ }
+ }
+ if (context != null) {
+ break;
+ }
+ }
- if (appContexts.size() > 0) return getWebBeansContext(appContexts);
+ if (context == null) {
+ context = contexts.get();
+ if (context == null) {
+ // Fallback strategy is to just grab the first AppContext and
assume it is the right one
+ // This kind of algorithm could be greatly improved
+ final List<AppContext> appContexts =
containerSystem.getAppContexts();
+ if (appContexts.size() > 0) {
+ return getWebBeansContext(appContexts);
+ }
- throw new IllegalStateException("On a thread without an
initialized context");
+ throw new IllegalStateException("On a thread without an
initialized context nor a classloader mapping a deployed app");
+ }
+ } else { // some cache to avoid to browse each app each time
+ contextByClassLoader.put(cl, context);
}
+
return context;
}
@@ -234,13 +279,15 @@ public class ThreadSingletonServiceImpl
@Override
public WebBeansContext get(Object key) {
- return getContext();
+ return getContext((ClassLoader) key);
}
@Override
public void clear(Object key) {
- contextMessage(getContext(), "clearing ");
- getContext().clear();
+ final WebBeansContext ctx = getContext((ClassLoader) key);
+ contextMessage(ctx, "clearing ");
+ contextByClassLoader.remove(key);
+ ctx.clear();
}
}