/* * Copyright to the original author or authors. * * Licensed 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.rioproject.impl.loader; import com.sun.jini.start.ClassLoaderUtil; import edu.emory.mathcs.util.classloader.URIClassLoader; import org.rioproject.loader.ServiceClassLoader; import org.rioproject.opstring.ClassBundle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; /** * Utility for loading classes defined by a {@link org.rioproject.opstring.ClassBundle} */ public class ClassBundleLoader { private static Logger logger = LoggerFactory.getLogger(ClassBundleLoader.class.getName()); /** * Load the class using resources in the {@code ClassBundle}. If there are no * resources for the class the parent ClassLoader will be used to load the * class. If there are resources (jars), a new ClassLoader will be created, * setting the delegating ClassLoader to the contextClassLoader * * @param bundle The ClassBundle to load * @return A new Class instance each time this method is invoked * * @throws ClassNotFoundException If the class cannot be loaded * @throws MalformedURLException If URLs cannot be created */ public static Class loadClass(ClassBundle bundle) throws ClassNotFoundException, MalformedURLException { Class theClass = null; final Thread currentThread = Thread.currentThread(); final ClassLoader cCL = AccessController.doPrivileged( new PrivilegedAction<ClassLoader>() { public ClassLoader run() { return (currentThread.getContextClassLoader()); } }); try { theClass = loadClass(cCL, bundle); } finally { AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { public ClassLoader run() { currentThread.setContextClassLoader(cCL); return (null); } }); } return theClass; } /** * Load the class using resources in the {@code ClassBundle}. If there are no * resources for the class the parent ClassLoader will be used to load the * class. If there are resources (jars), a new ClassLoader will be created. * * @param parent Parent ClassLoader to use for delegation. * @param bundle The ClassBundle to load * * @return A new Class instance each time this method is invoked * * @throws ClassNotFoundException If the class cannot be loaded * @throws MalformedURLException If URLs cannot be created */ public static Class loadClass(final ClassLoader parent, ClassBundle bundle) throws ClassNotFoundException, MalformedURLException { if(parent == null) throw new IllegalArgumentException("parent is null"); if(bundle == null) throw new IllegalArgumentException("bundle is null"); ClassLoader loader = parent; String className = bundle.getClassName(); URL[] urls = bundle.getJARs(); if(urls.length > 0) { try { loader = new URIClassLoader(ServiceClassLoader.getURIs(urls), parent); } catch (URISyntaxException e) { throw new MalformedURLException("Creating URIs"); } } if(logger.isTraceEnabled()) { logger.trace("Using ClassLoader [{}] to load class {}", loader.getClass().getName(), className); ClassLoaderUtil.displayClassLoaderTree(loader); } return (loader.loadClass(className)); } }