You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by da...@apache.org on 2007/01/13 19:25:30 UTC
svn commit: r495942 - in
/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks:
./ shielding/
Author: danielf
Date: Sat Jan 13 10:25:27 2007
New Revision: 495942
URL: http://svn.apache.org/viewvc?view=rev&rev=495942
Log:
Applied patch https://issues.apache.org/jira/browse/COCOON-1955 - Allow shielded class loading for a single block, from Alexander Klimetschek, Alexander Saar and Jörg Heinicke. The patch also implements some unimplemented methods in the BlockContext.
Added:
cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/
cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldedGroupClassLoaderManager.java
cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingBlockServlet.java
cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingClassLoaderInterceptor.java
Modified:
cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java
cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockServlet.java
Modified: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java?view=diff&rev=495942&r1=495941&r2=495942
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java (original)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java Sat Jan 13 10:25:27 2007
@@ -16,16 +16,22 @@
*/
package org.apache.cocoon.blocks;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
+import java.util.Vector;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
@@ -105,9 +111,6 @@
* @see javax.servlet.ServletContext#getResource(java.lang.String)
*/
public URL getResource(String path) throws MalformedURLException {
- if (path.length() == 0 || path.charAt(0) != '/')
- throw new MalformedURLException("The path must start with '/' " + path);
-
// hack for getting a file protocol or other protocols that can be used as context
// path in the getResource method in the servlet context
if (!(blockContextURL.startsWith("file:") || blockContextURL.startsWith("/")
@@ -129,7 +132,7 @@
// HACK: allow file:/ URLs for reloading of sitemaps during development
if (this.blockContextURL.startsWith("file:")) {
- return new URL(this.blockContextURL + path);
+ return new URL("file", null, this.blockContextURL.substring("file:".length()) + path);
} else {
if (this.blockContextURL.length() != 0 && this.blockContextURL.charAt(0) != '/')
throw new MalformedURLException("The blockContextURL must be empty or start with '/' "
@@ -180,8 +183,29 @@
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
public Enumeration getInitParameterNames() {
- // TODO Auto-generated method stub
- return null;
+ Vector names = new Vector();
+
+ // add all names of the parent servlet context
+ Enumeration enumeration = super.getInitParameterNames();
+ while (enumeration.hasMoreElements()) {
+ names.add(enumeration.nextElement());
+ }
+
+ // add names of the super block
+ ServletContext superContext = this.getNamedContext(SUPER);
+ if (superContext != null) {
+ enumeration = superContext.getInitParameterNames();
+ while (enumeration.hasMoreElements()) {
+ names.add(enumeration.nextElement());
+ }
+ }
+
+ // add property names of this block
+ if (this.properties != null) {
+ names.addAll(this.properties.keySet());
+ }
+
+ return names.elements();
}
/*
@@ -225,14 +249,54 @@
public int getMinorVersion() {
return 3;
}
+
+ private Collection getDirectoryList(File file, String pathPrefix) {
+ ArrayList filenames = new ArrayList();
+
+ if (!file.isDirectory()) {
+ filenames.add("/" + file.toString().substring(pathPrefix.length()-1));
+ return filenames;
+ }
+
+ File[] files = file.listFiles();
+
+ for (int i = 0; i < files.length; i++) {
+ File subfile = files[i];
+ filenames.addAll(getDirectoryList(subfile, pathPrefix));
+ }
+
+ return filenames;
+ }
/*
* (non-Javadoc)
*
* @see javax.servlet.ServletContext#getResourcePaths(java.lang.String)
*/
- public Set getResourcePaths(String arg0) {
- return null;
+ public Set getResourcePaths(String path) {
+ String pathPrefix;
+ if (this.blockContextURL.startsWith("file:")) {
+ pathPrefix = this.blockContextURL.substring("file:".length());
+ } else {
+ pathPrefix = this.blockContextURL;
+ }
+
+ path = pathPrefix + path;
+
+ if (path == null) {
+ return Collections.EMPTY_SET;
+ }
+
+ File file = new File(path);
+
+ if (!file.exists()) {
+ return Collections.EMPTY_SET;
+ }
+
+ HashSet set = new HashSet();
+ set.addAll(getDirectoryList(file, pathPrefix));
+
+ return set;
}
/*
@@ -319,6 +383,10 @@
*/
// FIXME implement NPE handling
public ServletContext getNamedContext(String name) {
+ if (this.connections == null) {
+ return null;
+ }
+
BlockServlet blockServlet =
(BlockServlet) this.connections.get(name);
return blockServlet != null ? blockServlet.getBlockContext() : null;
Modified: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockServlet.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockServlet.java?view=diff&rev=495942&r1=495941&r2=495942
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockServlet.java (original)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockServlet.java Sat Jan 13 10:25:27 2007
@@ -46,13 +46,18 @@
*/
public class BlockServlet extends HttpServlet
implements ApplicationContextAware, ServletContextAware, BeanNameAware, InitializingBean, DisposableBean {
+
private BlockContext blockContext;
- private String embededServletClass;
- private Servlet embededServlet;
+ private String embeddedServletClass;
+ private Servlet embeddedServlet;
private ServletContext servletContext;
private String beanName;
private ApplicationContext parentContainer;
+ public BlockServlet() {
+ this.blockContext = new BlockContext();
+ }
+
/* (non-Javadoc)
* @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
*/
@@ -71,7 +76,7 @@
container.setServletContext(this.blockContext);
container.refresh();
this.blockContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, container);
-
+
// create a servlet config based on the block servlet context
ServletConfig blockServletConfig =
new ServletConfigurationWrapper(servletConfig, this.blockContext) {
@@ -85,32 +90,26 @@
public Enumeration getInitParameterNames() {
return super.getServletContext().getInitParameterNames();
}
- };
-
+ };
+
// create and initialize the embeded servlet
- try {
- this.embededServlet =
- (Servlet) this.getClass().getClassLoader().loadClass(this.embededServletClass).newInstance();
- } catch (InstantiationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- this.embededServlet.init(blockServletConfig);
- this.blockContext.setServlet(this.embededServlet);
+ this.embeddedServlet = createEmbeddedServlet(this.embeddedServletClass, blockServletConfig);
+ this.embeddedServlet.init(blockServletConfig);
+ this.blockContext.setServlet(this.embeddedServlet);
}
-
- /* (non-Javadoc)
- * @see javax.servlet.GenericServlet#destroy()
+
+ /**
+ * Creates and initializes the embedded servlet
+ * @param string
+ * @throws ServletException
*/
- public void destroy() {
- this.embededServlet.destroy();
- super.destroy();
+ protected Servlet createEmbeddedServlet(String embeddedServletClassName, ServletConfig servletConfig)
+ throws ServletException {
+ try {
+ return (Servlet) this.getClass().getClassLoader().loadClass(embeddedServletClassName).newInstance();
+ } catch (Exception e) {
+ throw new ServletException("Loading class for embedded servlet failed " + embeddedServletClassName, e);
+ }
}
/* (non-Javadoc)
@@ -123,6 +122,11 @@
dispatcher.forward(request, response);
}
+ public void destroy() {
+ this.embeddedServlet.destroy();
+ super.destroy();
+ }
+
/**
* @return the blockContext
*/
@@ -130,10 +134,6 @@
return this.blockContext;
}
- public BlockServlet() {
- this.blockContext = new BlockContext();
- }
-
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.parentContainer = applicationContext;
}
@@ -166,7 +166,7 @@
}
public void setServletClass(String servletClass) {
- this.embededServletClass = servletClass;
+ this.embeddedServletClass = servletClass;
}
public void setProperties(Map properties) {
Added: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldedGroupClassLoaderManager.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldedGroupClassLoaderManager.java?view=auto&rev=495942
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldedGroupClassLoaderManager.java (added)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldedGroupClassLoaderManager.java Sat Jan 13 10:25:27 2007
@@ -0,0 +1,143 @@
+/*
+ * 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.cocoon.blocks.shielding;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.cocoon.classloader.ClassLoaderConfiguration;
+import org.apache.cocoon.classloader.ClassLoaderFactory;
+import org.apache.cocoon.classloader.DefaultClassLoaderFactory;
+
+/**
+ * Used by the ShieldingBlockServlet to obtain a shielded classloader. Supports
+ * groups of servlets that use the same classloader that is still shielded from
+ * the rest of the webapp.
+ */
+public class ShieldedGroupClassLoaderManager {
+
+ // parameters
+
+ public static final String SHIELDED_GROUP_PARAM = "shielded-group";
+
+ public static final String SHIELDED_LIB_PARAM = "shielded-lib";
+
+ public static final String SHIELDED_CLASSES_PARAM = "shielded-classes";
+
+ public static final String CLASSLOADER_FACTORY_PARAM = "classloader-factory";
+
+ // standard directories
+
+ /**
+ * Default directory for shielded libs (below COB-INF), must start with "/"
+ */
+ protected static final String SHIELDED_LIB = "shielded/lib";
+
+ /**
+ * Default directory for shielded classes (below COB-INF), must start with
+ * "/"
+ */
+ protected static final String SHIELDED_CLASSES = "shielded/classes";
+
+ /**
+ * Maps group names (Strings) to their classloader.
+ */
+ protected static Map groupClassloaders = new HashMap();
+
+ /**
+ * Get the classloader, either an already instantiated classloader for a
+ * group or create a completely new one.
+ */
+ public static synchronized ClassLoader getClassLoader(
+ ServletContext servletContext, Map parameters)
+ throws ServletException {
+ final String classLoaderGroup = (String) parameters
+ .get(SHIELDED_GROUP_PARAM);
+ if (classLoaderGroup != null) {
+ // check if the classloader for this group was already created
+ if (groupClassloaders.containsKey(classLoaderGroup)) {
+ return (ClassLoader) groupClassloaders.get(classLoaderGroup);
+ }
+ }
+
+ ClassLoader shieldedClassLoader;
+
+ shieldedClassLoader = createClassLoader(
+ ShieldedGroupClassLoaderManager.class.getClassLoader(),
+ servletContext, parameters);
+
+ // if this classloader is part of a group, add it to the map
+ if (classLoaderGroup != null) {
+ groupClassloaders.put(classLoaderGroup, shieldedClassLoader);
+ }
+
+ return shieldedClassLoader;
+ }
+
+ /**
+ * Create the shielded class loader.
+ */
+ protected static ClassLoader createClassLoader(ClassLoader parent,
+ ServletContext servletContext, Map parameters)
+ throws ServletException {
+ String classesDirectory = ShieldedGroupClassLoaderManager.SHIELDED_CLASSES;
+ String jarDirectory = ShieldedGroupClassLoaderManager.SHIELDED_LIB;
+
+ if (parameters.get(SHIELDED_CLASSES_PARAM) != null) {
+ classesDirectory = (String) parameters.get(SHIELDED_CLASSES_PARAM);
+ }
+ if (parameters.get(SHIELDED_LIB_PARAM) != null) {
+ jarDirectory = (String) parameters.get(SHIELDED_LIB_PARAM);
+ }
+
+ ClassLoaderConfiguration config = new ClassLoaderConfiguration();
+ config.addClassDirectory(classesDirectory);
+ config.addLibDirectory(jarDirectory);
+
+ String factoryClassName = DefaultClassLoaderFactory.class.getName();
+ if (parameters.get(CLASSLOADER_FACTORY_PARAM) != null) {
+ factoryClassName = (String) parameters.get(CLASSLOADER_FACTORY_PARAM);
+ }
+
+ try {
+ final Class classLoaderFactoryClass = Class.forName(factoryClassName);
+ ClassLoaderFactory factory = (ClassLoaderFactory) classLoaderFactoryClass.newInstance();
+ return factory.createClassLoader(
+ config.getClass().getClassLoader(), config, servletContext);
+ } catch (InstantiationException e) {
+ throw new ServletException(e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ throw new ServletException(e.getMessage(), e);
+ } catch (ClassNotFoundException e) {
+ throw new ServletException(e.getMessage(), e);
+ } catch (SecurityException e) {
+ throw new ServletException(e.getMessage(), e);
+ } catch (NoSuchMethodException e) {
+ throw new ServletException(e.getMessage(), e);
+ } catch (IllegalArgumentException e) {
+ throw new ServletException(e.getMessage(), e);
+ } catch (InvocationTargetException e) {
+ throw new ServletException(e.getMessage(), e);
+ } catch (Exception e) {
+ throw new ServletException(e.getMessage(), e);
+ }
+ }
+}
Added: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingBlockServlet.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingBlockServlet.java?view=auto&rev=495942
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingBlockServlet.java (added)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingBlockServlet.java Sat Jan 13 10:25:27 2007
@@ -0,0 +1,115 @@
+/*
+ * 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.cocoon.blocks.shielding;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+
+import org.apache.cocoon.blocks.BlockServlet;
+
+import org.springframework.aop.framework.ProxyFactory;
+
+/**
+ * A servlet for use in cocoon blocks that adds shielded classloading support.
+ */
+public class ShieldingBlockServlet extends BlockServlet {
+
+ /**
+ * Spring property, name of the group that will get the same classloader.
+ */
+ protected String shieldedGroup;
+
+ /**
+ * Spring property, path to the shielded libraries (jars) inside COB-INF/
+ */
+ protected String shieldedLib;
+
+ /**
+ * Spring property, path to the shielded classes inside COB-INF/
+ */
+ protected String shieldedClasses;
+
+ /**
+ * Spring property, name of the classloader factory
+ */
+ protected String classLoaderFactory;
+
+ protected ClassLoader classLoader;
+
+ public void setShieldedGroup(String shieldedGroup) {
+ this.shieldedGroup = shieldedGroup;
+ }
+
+ public void setShieldedLib(String shieldedLib) {
+ if (!shieldedLib.startsWith("/")) {
+ this.shieldedLib = "/" + shieldedLib;
+ } else {
+ this.shieldedLib = shieldedLib;
+ }
+ }
+
+ public void setShieldedClasses(String shieldedClasses) {
+ if (!shieldedClasses.startsWith("/")) {
+ this.shieldedClasses = "/" + shieldedClasses;
+ } else {
+ this.shieldedClasses = shieldedClasses;
+ }
+ }
+
+ public void setClassLoaderFactory(String classLoaderFactory) {
+ this.classLoaderFactory = classLoaderFactory;
+ }
+
+ protected Servlet createEmbeddedServlet(String embeddedServletClassName, ServletConfig servletConfig)
+ throws ServletException {
+ // create the classloader
+ Map parameters = new HashMap();
+ parameters.put(ShieldedGroupClassLoaderManager.SHIELDED_GROUP_PARAM,
+ this.shieldedGroup);
+ parameters.put(ShieldedGroupClassLoaderManager.SHIELDED_LIB_PARAM,
+ this.shieldedLib);
+ parameters.put(ShieldedGroupClassLoaderManager.SHIELDED_CLASSES_PARAM,
+ this.shieldedClasses);
+ parameters.put(ShieldedGroupClassLoaderManager.CLASSLOADER_FACTORY_PARAM,
+ this.classLoaderFactory);
+
+ this.classLoader =
+ ShieldedGroupClassLoaderManager.getClassLoader(getBlockContext(), parameters);
+
+ // Create the servlet
+ final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(this.classLoader);
+
+ Class servletClass = this.classLoader.loadClass(embeddedServletClassName);
+ Servlet embeddedServlet = (Servlet) servletClass.newInstance();
+ ProxyFactory proxyFactory = new ProxyFactory(embeddedServlet);
+ proxyFactory.addAdvice(new ShieldingClassLoaderInterceptor(this.classLoader));
+ return (Servlet) proxyFactory.getProxy();
+ } catch (Exception e) {
+ throw new ServletException(
+ "Loading class for embedded servlet failed " + embeddedServletClassName, e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldClassLoader);
+ }
+ }
+
+}
Added: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingClassLoaderInterceptor.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingClassLoaderInterceptor.java?view=auto&rev=495942
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingClassLoaderInterceptor.java (added)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/shielding/ShieldingClassLoaderInterceptor.java Sat Jan 13 10:25:27 2007
@@ -0,0 +1,41 @@
+/*
+ * 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.cocoon.blocks.shielding;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+public class ShieldingClassLoaderInterceptor implements MethodInterceptor {
+
+ private final ClassLoader classLoader;
+
+ public ShieldingClassLoaderInterceptor(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(this.classLoader);
+
+ return invocation.proceed();
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldClassLoader);
+ }
+ }
+
+}