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);
+        }
+    }
+
+}