/* * JBoss, Home of Professional Open Source. * Copyright 2006, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.web.tomcat.service; import java.net.URL; import org.apache.catalina.loader.WebappClassLoader; import org.jboss.logging.Logger; import org.jboss.proxy.compiler.IIOPStubCompiler; /** * Subclass the tomcat web app class loader to override the filter method to * exclude classes which cannot be override by the web app due to their use in * the tomcat web container/integration. * * @author Scott.Stark@jboss.org * @version $Revision: 85945 $ */ public class WebAppClassLoader extends WebappClassLoader { static Logger log = Logger.getLogger(WebAppClassLoader.class); private String[] filteredPackages = {"org.apache.commons.logging"}; public WebAppClassLoader() { } public WebAppClassLoader(ClassLoader parent) { super(parent); } public String[] getFilteredPackages() { return filteredPackages; } public void setFilteredPackages(String[] pkgs) { this.filteredPackages = pkgs; } /* * (non-Javadoc) * @see org.apache.catalina.loader.WebappClassLoader#addURL(java.net.URL) */ @Override public void addURL(URL url) { super.addURL(url); } @Override public URL[] getURLs() { return new URL[0]; // Optimize away the Memory Allocation } /* * (non-Javadoc) * @see org.apache.catalina.loader.WebappClassLoader#findClass(java.lang.String) */ @Override public Class findClass(String name) throws ClassNotFoundException { boolean trace = log.isTraceEnabled(); if (trace) log.trace("findClass(" + name + ") called"); try { return super.findClass(name); } catch (ClassNotFoundException cnfe) { // try to dynamically generate the class if it is a stub int start = name.lastIndexOf('.') + 1; if (name.charAt(start) == '_' && name.endsWith("_Stub")) return generateStub(name); throw cnfe; } } /** * <p> * Generate iiop stubs dynamically for any name ending in _Stub. * </p> * * @param name a <code>String</code> representing the stub fully-qualified class name. * @return the <code>Class</code> of the generated stub. * @throws ClassNotFoundException if the stub class could not be created. */ private Class generateStub(String name) throws ClassNotFoundException { boolean trace = log.isTraceEnabled(); int start = name.lastIndexOf('.') + 1; String pkg = name.substring(0, start); String interfaceName = pkg + name.substring(start + 1, name.length() - 5); // This is a workaround for a problem in the RMI/IIOP // stub loading code in SUN JDK 1.4.x, which prepends // "org.omg.stub." to classes in certain name spaces, // such as "com.sun". This non-compliant behavior // results in failures when deploying SUN example code, // including ECPerf and PetStore, so we remove the prefix. if (interfaceName.startsWith("org.omg.stub.com.sun.")) interfaceName = interfaceName.substring(13); Class intf = super.loadClass(interfaceName); if (trace) log.trace("loaded class " + interfaceName); byte[] code = IIOPStubCompiler.compile(intf, name); if (trace) log.trace("compiled stub class for " + interfaceName); Class clz = super.defineClass(name, code, 0, code.length); if (trace) log.trace("defined stub class for " + interfaceName); super.resolveClass(clz); try { clz.newInstance(); } catch (Throwable t) { ClassNotFoundException cnfe = new ClassNotFoundException(interfaceName, t); throw cnfe; } if (trace) log.trace("resolved stub class for " + interfaceName); return clz; } /** * Overriden to filter out classes in the packages listed in the * filteredPackages settings. * * @param name * @return true if the class should be loaded from the parent class loader, * false if it can be loaded from this class loader. */ protected boolean filter(String name) { boolean excludeClass = super.filter(name); if (excludeClass == false) { // Check class against our filtered packages int length = filteredPackages != null ? filteredPackages.length : 0; for (int n = 0; n < length; n++) { String pkg = filteredPackages[n]; if (name.startsWith(pkg)) { excludeClass = true; break; } } } log.trace("filter name=" + name + ", exclude=" + excludeClass); return excludeClass; } }