KYLIN-2361 add Tomcat8 ordered class loader
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/9a3bd71c Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/9a3bd71c Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/9a3bd71c Branch: refs/heads/KYLIN-2361 Commit: 9a3bd71c8e5ce9dc13e38560efc556dc862819a1 Parents: 2b60ac6 Author: Billy Liu <billy...@apache.org> Authored: Sat Feb 4 11:41:49 2017 +0800 Committer: Billy Liu <billy...@apache.org> Committed: Sat Feb 4 11:42:02 2017 +0800 ---------------------------------------------------------------------- .../kylin/ext/CustomizedWebappClassloader.java | 4 +- .../kylin/ext/OrderedWebResourceRoot.java | 286 +++++++++++++++++++ .../kylin/ext/WebappOrderedClassLoader.java | 66 +++++ 3 files changed, 353 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/9a3bd71c/tomcat-ext/src/main/java/org/apache/kylin/ext/CustomizedWebappClassloader.java ---------------------------------------------------------------------- diff --git a/tomcat-ext/src/main/java/org/apache/kylin/ext/CustomizedWebappClassloader.java b/tomcat-ext/src/main/java/org/apache/kylin/ext/CustomizedWebappClassloader.java index f241865..bbf4053 100644 --- a/tomcat-ext/src/main/java/org/apache/kylin/ext/CustomizedWebappClassloader.java +++ b/tomcat-ext/src/main/java/org/apache/kylin/ext/CustomizedWebappClassloader.java @@ -18,14 +18,12 @@ package org.apache.kylin.ext; -import org.apache.catalina.loader.ParallelWebappClassLoader; - /** * simple extension to standard ParallelWebappClassLoader * the only difference is that CustomizedWebappClassloader is able to delegate more packages * to parent classloaders */ -public class CustomizedWebappClassloader extends ParallelWebappClassLoader { +public class CustomizedWebappClassloader extends WebappOrderedClassLoader { /** * Set of package names which are not allowed to be loaded from a webapp * class loader without delegating first. http://git-wip-us.apache.org/repos/asf/kylin/blob/9a3bd71c/tomcat-ext/src/main/java/org/apache/kylin/ext/OrderedWebResourceRoot.java ---------------------------------------------------------------------- diff --git a/tomcat-ext/src/main/java/org/apache/kylin/ext/OrderedWebResourceRoot.java b/tomcat-ext/src/main/java/org/apache/kylin/ext/OrderedWebResourceRoot.java new file mode 100644 index 0000000..9784bd8 --- /dev/null +++ b/tomcat-ext/src/main/java/org/apache/kylin/ext/OrderedWebResourceRoot.java @@ -0,0 +1,286 @@ +/* + * 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.kylin.ext; + +import java.io.InputStream; +import java.net.URL; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +import org.apache.catalina.Context; +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; + +public class OrderedWebResourceRoot implements WebResourceRoot { + + private static final String WEB_INF_LIB_PATH = "/WEB-INF/lib"; + + private static final Comparator<WebResource> WEB_RESOURCE_COMPARATOR = new Comparator<WebResource>() { + @Override + public int compare(WebResource o1, WebResource o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + private WebResourceRoot delegate; + + public OrderedWebResourceRoot(WebResourceRoot delegate) { + this.delegate = delegate; + } + + @Override + public WebResource[] listResources(String path) { + WebResource[] webResources = delegate.listResources(path); + + if (WEB_INF_LIB_PATH.equals(path)) { + Arrays.sort(webResources, WEB_RESOURCE_COMPARATOR); + } + + return webResources; + } + + @Override + public void addLifecycleListener(LifecycleListener listener) { + delegate.addLifecycleListener(listener); + } + + @Override + public LifecycleListener[] findLifecycleListeners() { + return delegate.findLifecycleListeners(); + } + + @Override + public void removeLifecycleListener(LifecycleListener listener) { + delegate.removeLifecycleListener(listener); + } + + @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(); + } + + @Override + public LifecycleState getState() { + return delegate.getState(); + } + + @Override + public String getStateName() { + return delegate.getStateName(); + } + + @Override + public WebResource getResource(String path) { + return delegate.getResource(path); + } + + @Override + public WebResource[] getResources(String path) { + return delegate.getResources(path); + } + + @Override + public WebResource getClassLoaderResource(String path) { + return delegate.getClassLoaderResource(path); + } + + @Override + public WebResource[] getClassLoaderResources(String path) { + return delegate.getClassLoaderResources(path); + } + + @Override + public String[] list(String path) { + return delegate.list(path); + } + + @Override + public Set<String> listWebAppPaths(String path) { + return delegate.listWebAppPaths(path); + } + + @Override + public boolean mkdir(String path) { + return delegate.mkdir(path); + } + + @Override + public boolean write(String path, InputStream is, boolean overwrite) { + return delegate.write(path, is, overwrite); + } + + @Override + public void createWebResourceSet(ResourceSetType type, String webAppMount, URL url, String internalPath) { + delegate.createWebResourceSet(type, webAppMount, url, internalPath); + } + + @Override + public void createWebResourceSet(ResourceSetType type, String webAppMount, String base, String archivePath, + String internalPath) { + delegate.createWebResourceSet(type, webAppMount, base, archivePath, internalPath); + } + + @Override + public void addPreResources(WebResourceSet webResourceSet) { + delegate.addPreResources(webResourceSet); + } + + @Override + public WebResourceSet[] getPreResources() { + return delegate.getPreResources(); + } + + @Override + public void addJarResources(WebResourceSet webResourceSet) { + delegate.addJarResources(webResourceSet); + } + + @Override + public WebResourceSet[] getJarResources() { + return delegate.getJarResources(); + } + + @Override + public void addPostResources(WebResourceSet webResourceSet) { + delegate.addPostResources(webResourceSet); + } + + @Override + public WebResourceSet[] getPostResources() { + return delegate.getPostResources(); + } + + @Override + public Context getContext() { + return delegate.getContext(); + } + + @Override + public void setContext(Context context) { + delegate.setContext(context); + } + + @Override + public void setAllowLinking(boolean allowLinking) { + delegate.setAllowLinking(allowLinking); + } + + @Override + public boolean getAllowLinking() { + return delegate.getAllowLinking(); + } + + @Override + public void setCachingAllowed(boolean cachingAllowed) { + delegate.setCachingAllowed(cachingAllowed); + } + + @Override + public boolean isCachingAllowed() { + return delegate.isCachingAllowed(); + } + + @Override + public void setCacheTtl(long ttl) { + delegate.setCacheTtl(ttl); + } + + @Override + public long getCacheTtl() { + return delegate.getCacheTtl(); + } + + @Override + public void setCacheMaxSize(long cacheMaxSize) { + delegate.setCacheMaxSize(cacheMaxSize); + } + + @Override + public long getCacheMaxSize() { + return delegate.getCacheMaxSize(); + } + + @Override + public void setCacheObjectMaxSize(int cacheObjectMaxSize) { + delegate.setCacheObjectMaxSize(cacheObjectMaxSize); + } + + @Override + public int getCacheObjectMaxSize() { + return delegate.getCacheObjectMaxSize(); + } + + @Override + public void setTrackLockedFiles(boolean trackLockedFiles) { + delegate.setTrackLockedFiles(trackLockedFiles); + } + + @Override + public boolean getTrackLockedFiles() { + return delegate.getTrackLockedFiles(); + } + + @Override + public void backgroundProcess() { + delegate.backgroundProcess(); + } + + @Override + public void registerTrackedResource(TrackedWebResource trackedResource) { + delegate.registerTrackedResource(trackedResource); + } + + @Override + public void deregisterTrackedResource(TrackedWebResource trackedResource) { + delegate.deregisterTrackedResource(trackedResource); + } + + @Override + public List<URL> getBaseUrls() { + return delegate.getBaseUrls(); + } + + @Override + public void gc() { + delegate.gc(); + } + +} http://git-wip-us.apache.org/repos/asf/kylin/blob/9a3bd71c/tomcat-ext/src/main/java/org/apache/kylin/ext/WebappOrderedClassLoader.java ---------------------------------------------------------------------- diff --git a/tomcat-ext/src/main/java/org/apache/kylin/ext/WebappOrderedClassLoader.java b/tomcat-ext/src/main/java/org/apache/kylin/ext/WebappOrderedClassLoader.java new file mode 100644 index 0000000..6a90e55 --- /dev/null +++ b/tomcat-ext/src/main/java/org/apache/kylin/ext/WebappOrderedClassLoader.java @@ -0,0 +1,66 @@ +/* + * 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.kylin.ext; + +import org.apache.catalina.LifecycleException; +import org.apache.catalina.WebResourceRoot; +import org.apache.catalina.loader.ParallelWebappClassLoader; + +/** + * Modified from the openwide-java/tomcat-classloader-ordered in https://github.com/openwide-java/tomcat-classloader-ordered + * + * This classloader is designed to return the jar of WEB-INF lib in alphabetical order as it was the case with Tomcat + * 7.x. + * + * See the discussion in https://bz.apache.org/bugzilla/show_bug.cgi?id=57129 for more information. + */ +public class WebappOrderedClassLoader extends ParallelWebappClassLoader { + + public WebappOrderedClassLoader() { + } + + public WebappOrderedClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + public void setResources(WebResourceRoot resources) { + super.setResources(new OrderedWebResourceRoot(resources)); + } + + @Override + public WebappOrderedClassLoader copyWithoutTransformers() { + WebappOrderedClassLoader result = new WebappOrderedClassLoader(getParent()); + + super.copyStateWithoutTransformers(result); + + try { + result.start(); + } catch (LifecycleException e) { + throw new IllegalStateException(e); + } + + return result; + } + + @Override + protected Object getClassLoadingLock(String className) { + return this; + } +} \ No newline at end of file