You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2015/04/20 13:07:59 UTC
tomee git commit: binding WebResourceRoot (stop part) lifecycle to
the TomEEWebAppClassLoader to ensure we dont eagerly close resources. TODO:
see if we can merge openejb and tomcat lifecycle in a better manner
Repository: tomee
Updated Branches:
refs/heads/master 757e4e83f -> 1665a38f5
binding WebResourceRoot (stop part) lifecycle to the TomEEWebAppClassLoader to ensure we dont eagerly close resources. TODO: see if we can merge openejb and tomcat lifecycle in a better manner
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/1665a38f
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/1665a38f
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/1665a38f
Branch: refs/heads/master
Commit: 1665a38f5c850b656be14ae94285ee369dea90a7
Parents: 757e4e8
Author: Romain Manni-Bucau <rm...@apache.org>
Authored: Mon Apr 20 13:07:44 2015 +0200
Committer: Romain Manni-Bucau <rm...@apache.org>
Committed: Mon Apr 20 13:07:44 2015 +0200
----------------------------------------------------------------------
.../tomee/catalina/LazyStopStandardRoot.java | 327 +++++++++++++++++++
.../tomee/catalina/TomEEWebappClassLoader.java | 36 +-
.../tomee/catalina/TomcatWebAppBuilder.java | 48 ++-
3 files changed, 386 insertions(+), 25 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/1665a38f/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopStandardRoot.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopStandardRoot.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopStandardRoot.java
new file mode 100644
index 0000000..80a49af
--- /dev/null
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopStandardRoot.java
@@ -0,0 +1,327 @@
+/*
+ * 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.tomee.catalina;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.JmxEnabled;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.TrackedWebResource;
+import org.apache.catalina.WebResource;
+import org.apache.catalina.WebResourceRoot;
+import org.apache.catalina.WebResourceSet;
+import org.apache.catalina.util.LifecycleMBeanBase;
+import org.apache.catalina.webresources.StandardRoot;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.Set;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+public class LazyStopStandardRoot implements WebResourceRoot, JmxEnabled {
+ private final WebResourceRoot delegate;
+ private final boolean isJmxEnabled;
+ private final boolean isLifecycleMBeanBase;
+
+ public LazyStopStandardRoot(final WebResourceRoot delegate) {
+ this.delegate = delegate;
+ this.isJmxEnabled = JmxEnabled.class.isInstance(delegate);
+ this.isLifecycleMBeanBase = LifecycleMBeanBase.class.isInstance(delegate);
+ }
+
+ @Override
+ public String[] list(final String path) {
+ return delegate.list(path);
+ }
+
+ @Override
+ public Set<String> listWebAppPaths(final String path) {
+ return delegate.listWebAppPaths(path);
+ }
+
+ @Override
+ public boolean mkdir(final String path) {
+ return delegate.mkdir(path);
+ }
+
+ @Override
+ public boolean write(final String path, final InputStream is, final boolean overwrite) {
+ return delegate.write(path, is, overwrite);
+ }
+
+ @Override
+ public WebResource getResource(final String path) {
+ return delegate.getResource(path);
+ }
+
+ @Override
+ public WebResource getClassLoaderResource(final String path) {
+ return delegate.getClassLoaderResource(path);
+ }
+
+ @Override
+ public WebResource[] getClassLoaderResources(final String path) {
+ return delegate.getClassLoaderResources(path);
+ }
+
+ @Override
+ public WebResource[] getResources(final String path) {
+ return delegate.getResources(path);
+ }
+
+ @Override
+ public WebResource[] listResources(final String path) {
+ return delegate.listResources(path);
+ }
+
+ @Override
+ public void createWebResourceSet(final ResourceSetType type, final String webAppMount, final URL url, final String internalPath) {
+ delegate.createWebResourceSet(type, webAppMount, url, internalPath);
+ }
+
+ @Override
+ public void createWebResourceSet(final ResourceSetType type, final String webAppMount, final String base, final String archivePath, final String internalPath) {
+ delegate.createWebResourceSet(type, webAppMount, base, archivePath, internalPath);
+ }
+
+ @Override
+ public void addPreResources(final WebResourceSet webResourceSet) {
+ delegate.addPreResources(webResourceSet);
+ }
+
+ @Override
+ public WebResourceSet[] getPreResources() {
+ return delegate.getPreResources();
+ }
+
+ @Override
+ public void addJarResources(final WebResourceSet webResourceSet) {
+ delegate.addJarResources(webResourceSet);
+ }
+
+ @Override
+ public WebResourceSet[] getJarResources() {
+ return delegate.getJarResources();
+ }
+
+ @Override
+ public void addPostResources(final WebResourceSet webResourceSet) {
+ delegate.addPostResources(webResourceSet);
+ }
+
+ @Override
+ public WebResourceSet[] getPostResources() {
+ return delegate.getPostResources();
+ }
+
+ @Override
+ public void setAllowLinking(final boolean allowLinking) {
+ delegate.setAllowLinking(allowLinking);
+ }
+
+ @Override
+ public boolean getAllowLinking() {
+ return delegate.getAllowLinking();
+ }
+
+ @Override
+ public void setCachingAllowed(final boolean cachingAllowed) {
+ delegate.setCachingAllowed(cachingAllowed);
+ }
+
+ @Override
+ public boolean isCachingAllowed() {
+ return delegate.isCachingAllowed();
+ }
+
+ @Override
+ public long getCacheTtl() {
+ return delegate.getCacheTtl();
+ }
+
+ @Override
+ public void setCacheTtl(final long cacheTtl) {
+ delegate.setCacheTtl(cacheTtl);
+ }
+
+ @Override
+ public long getCacheMaxSize() {
+ return delegate.getCacheMaxSize();
+ }
+
+ @Override
+ public void setCacheMaxSize(final long cacheMaxSize) {
+ delegate.setCacheMaxSize(cacheMaxSize);
+ }
+
+ @Override
+ public void setCacheObjectMaxSize(final int cacheObjectMaxSize) {
+ delegate.setCacheObjectMaxSize(cacheObjectMaxSize);
+ }
+
+ @Override
+ public int getCacheObjectMaxSize() {
+ return delegate.getCacheObjectMaxSize();
+ }
+
+ @Override
+ public void setTrackLockedFiles(final boolean trackLockedFiles) {
+ delegate.setTrackLockedFiles(trackLockedFiles);
+ }
+
+ @Override
+ public boolean getTrackLockedFiles() {
+ return delegate.getTrackLockedFiles();
+ }
+
+ public List<String> getTrackedResources() { // IDE?
+ return StandardRoot.class.cast(delegate).getTrackedResources();
+ }
+
+ @Override
+ public Context getContext() {
+ return delegate.getContext();
+ }
+
+ @Override
+ public void setContext(final Context context) {
+ delegate.setContext(context);
+ }
+
+ @Override
+ public void backgroundProcess() {
+ delegate.backgroundProcess();
+ }
+
+ @Override
+ public void gc() {
+ delegate.gc();
+ }
+
+ @Override
+ public void registerTrackedResource(final TrackedWebResource trackedResource) {
+ delegate.registerTrackedResource(trackedResource);
+ }
+
+ @Override
+ public void deregisterTrackedResource(final TrackedWebResource trackedResource) {
+ delegate.deregisterTrackedResource(trackedResource);
+ }
+
+ @Override
+ public List<URL> getBaseUrls() {
+ return delegate.getBaseUrls();
+ }
+
+ public void setDomain(final String domain) {
+ if (isJmxEnabled) {
+ JmxEnabled.class.cast(delegate).setDomain(domain);
+ }
+ }
+
+ public String getDomain() {
+ if (isJmxEnabled) {
+ return JmxEnabled.class.cast(delegate).getDomain();
+ }
+ return null;
+ }
+
+ public ObjectName getObjectName() {
+ if (isJmxEnabled) {
+ return JmxEnabled.class.cast(delegate).getObjectName();
+ }
+ return null;
+ }
+
+ public void postDeregister() {
+ if (isLifecycleMBeanBase) {
+ LifecycleMBeanBase.class.cast(delegate).postDeregister();
+ }
+ }
+
+ public void postRegister(final Boolean registrationDone) {
+ if (isLifecycleMBeanBase) {
+ LifecycleMBeanBase.class.cast(delegate).postRegister(registrationDone);
+ }
+ }
+
+ public void preDeregister() throws Exception {
+ if (isLifecycleMBeanBase) {
+ LifecycleMBeanBase.class.cast(delegate).preDeregister();
+ }
+ }
+
+ public ObjectName preRegister(final MBeanServer server, final ObjectName name) throws Exception {
+ if (isLifecycleMBeanBase) {
+ return LifecycleMBeanBase.class.cast(delegate).preRegister(server, name);
+ }
+ return name;
+ }
+
+ @Override
+ public void addLifecycleListener(final LifecycleListener listener) {
+ delegate.addLifecycleListener(listener);
+ }
+
+ @Override
+ public LifecycleListener[] findLifecycleListeners() {
+ return delegate.findLifecycleListeners();
+ }
+
+ @Override
+ public void removeLifecycleListener(final LifecycleListener listener) {
+ delegate.removeLifecycleListener(listener);
+ }
+
+ @Override
+ public LifecycleState getState() {
+ return delegate.getState();
+ }
+
+ @Override
+ public String getStateName() {
+ return delegate.getStateName();
+ }
+
+ @Override
+ public void init() throws LifecycleException {
+ delegate.init();
+ }
+
+ @Override
+ public void start() throws LifecycleException {
+ delegate.start();
+ }
+
+ @Override
+ public void stop() throws LifecycleException {
+ // delegate.stop();
+ }
+
+ @Override
+ public void destroy() throws LifecycleException {
+ // delegate.destroy();
+ }
+
+ public void internalStop() throws LifecycleException {
+ delegate.stop();
+ delegate.destroy();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/1665a38f/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomEEWebappClassLoader.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomEEWebappClassLoader.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomEEWebappClassLoader.java
index 9930946..e2364e6 100644
--- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomEEWebappClassLoader.java
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomEEWebappClassLoader.java
@@ -80,7 +80,7 @@ public class TomEEWebappClassLoader extends ParallelWebappClassLoader {
public static final String CLASS_EXTENSION = ".class";
private boolean restarting;
- private boolean forceStopPhase = Boolean.parseBoolean(SystemInstance.get().getProperty("tomee.webappclassloader.force-stop-phase", "true"));
+ private boolean forceStopPhase = Boolean.parseBoolean(SystemInstance.get().getProperty("tomee.webappclassloader.force-stop-phase", "false"));
private ClassLoaderConfigurer configurer;
private final boolean isEar;
private final ClassLoader containerClassLoader;
@@ -89,6 +89,7 @@ public class TomEEWebappClassLoader extends ParallelWebappClassLoader {
private Collection<File> additionalRepos;
private volatile boolean stopped = false;
private final Map<String, Boolean> filterTempCache = new HashMap<>(); // used only in sync block + isEar
+ private volatile LazyStopStandardRoot webResourceRoot;
public TomEEWebappClassLoader() {
hashCode = construct();
@@ -263,9 +264,16 @@ public class TomEEWebappClassLoader extends ParallelWebappClassLoader {
thread.setContextClassLoader(this);
try {
super.stop();
+ super.destroy();
+ if (webResourceRoot != null) {
+ webResourceRoot.internalStop();
+ }
stopped = true;
} finally {
thread.setContextClassLoader(loader);
+ if (!forceStopPhase) {
+ cleanUpClassLoader();
+ }
}
}
@@ -281,6 +289,10 @@ public class TomEEWebappClassLoader extends ParallelWebappClassLoader {
return restarting;
}
+ public boolean isForceStopPhase() {
+ return forceStopPhase;
+ }
+
public boolean isStopped() {
return stopped;
}
@@ -432,16 +444,22 @@ public class TomEEWebappClassLoader extends ParallelWebappClassLoader {
@Override
public void destroy() {
- try {
- super.destroy();
- } finally {
- final LogManager lm = LogManager.getLogManager();
- if (ClassLoaderLogManager.class.isInstance(lm)) { // weak ref but ensure it is really removed otherwise in some cases we leak
- Map.class.cast(Reflections.get(lm, "classLoaderLoggers")).remove(this);
+ if (forceStopPhase) {
+ try {
+ super.destroy();
+ } finally {
+ cleanUpClassLoader();
}
}
}
+ private void cleanUpClassLoader() {
+ final LogManager lm = LogManager.getLogManager();
+ if (ClassLoaderLogManager.class.isInstance(lm)) { // weak ref but ensure it is really removed otherwise in some cases we leak
+ Map.class.cast(Reflections.get(lm, "classLoaderLoggers")).remove(this);
+ }
+ }
+
public static void initContext(final ClassLoaderConfigurer configurer) {
INIT_CONFIGURER.set(configurer);
}
@@ -455,6 +473,10 @@ public class TomEEWebappClassLoader extends ParallelWebappClassLoader {
CONTEXT.remove();
}
+ public void setWebResourceRoot(LazyStopStandardRoot webResourceRoot) {
+ this.webResourceRoot = webResourceRoot;
+ }
+
private static class NoClassClassLoader extends ClassLoader {
private static final NoClassClassLoader INSTANCE = new NoClassClassLoader();
http://git-wip-us.apache.org/repos/asf/tomee/blob/1665a38f/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
index 319293a..fbf604b 100644
--- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
@@ -106,6 +106,7 @@ import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.URLs;
import org.apache.openejb.util.proxy.LocalBeanProxyFactory;
+import org.apache.openejb.util.reflection.Reflections;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.JarScanFilter;
import org.apache.tomcat.util.descriptor.web.ApplicationParameter;
@@ -130,22 +131,6 @@ import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.spi.adaptor.ELAdaptor;
import org.omg.CORBA.ORB;
-import javax.ejb.spi.HandleDelegate;
-import javax.el.ELResolver;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingException;
-import javax.naming.Reference;
-import javax.naming.StringRefAddr;
-import javax.servlet.ServletContext;
-import javax.servlet.SessionTrackingMode;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.jsp.JspApplicationContext;
-import javax.servlet.jsp.JspFactory;
-import javax.sql.DataSource;
-import javax.transaction.TransactionManager;
-import javax.transaction.TransactionSynchronizationRegistry;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -169,6 +154,22 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
+import javax.ejb.spi.HandleDelegate;
+import javax.el.ELResolver;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import javax.servlet.ServletContext;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspApplicationContext;
+import javax.servlet.jsp.JspFactory;
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
import static java.util.Arrays.asList;
import static org.apache.tomee.catalina.Contexts.warPath;
@@ -1510,7 +1511,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare
// skip undeployment if restarting
final TomEEWebappClassLoader tomEEWebappClassLoader = lazyClassLoader(
- org.apache.catalina.Context.class.isInstance(child)? org.apache.catalina.Context.class.cast(child) : null);
+ org.apache.catalina.Context.class.isInstance(child) ? org.apache.catalina.Context.class.cast(child) : null);
if (tomEEWebappClassLoader != null && tomEEWebappClassLoader.isRestarting()) {
return true;
}
@@ -1846,9 +1847,20 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare
*/
@Override
public void beforeStop(final StandardContext standardContext) {
+ final ClassLoader classLoader = standardContext.getLoader().getClassLoader();
+
// if it is not our custom loader clean up now otherwise wait afterStop
if (!(standardContext.getLoader() instanceof LazyStopLoader)) {
- jsfClasses.remove(standardContext.getLoader().getClassLoader());
+ jsfClasses.remove(classLoader);
+ }
+
+ // ensure we can stop it lazily - before all was in the classloader, now we align webresourceroot on the classloader config
+ // we wrap it only here to not modify at all runtime
+ if (!LazyStopStandardRoot.class.isInstance(standardContext.getResources())
+ && TomEEWebappClassLoader.class.isInstance(classLoader) && !TomEEWebappClassLoader.class.cast(classLoader).isForceStopPhase()) {
+ final LazyStopStandardRoot standardRoot = new LazyStopStandardRoot(standardContext.getResources());
+ Reflections.set(standardContext, "resources", standardRoot);
+ TomEEWebappClassLoader.class.cast(classLoader).setWebResourceRoot(standardRoot); // cause Assembler relies on the classloader only
}
}