/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Tom Tromey (tromey@redhat.com) - patch for bug 40972 *******************************************************************************/ package org.eclipse.ant.internal.core; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; public class AntClassLoader extends URLClassLoader { private static final String ANT_PACKAGES_PREFIX = "org.apache.tools"; //$NON-NLS-1$ private static final String ANT_URL_PREFIX = "org/apache/tools"; //$NON-NLS-1$ private boolean fAllowPluginLoading = false; protected ClassLoader[] fPluginLoaders; private ClassLoader fContextClassloader = null; public AntClassLoader(URL[] urls, ClassLoader[] pluginLoaders) { super(urls, ClassLoader.getSystemClassLoader()); fPluginLoaders = pluginLoaders; } /* * @see java.net.URLClassLoader#findClass(java.lang.String) */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class<?> result = null; // check whether to load the Apache Ant classes from the plug-in class loaders // or to only load from the URLs specified from the Ant runtime classpath preferences setting if (fAllowPluginLoading || !(name.startsWith(ANT_PACKAGES_PREFIX))) { result = loadClassPlugins(name); } if (result != null) { return result; } return super.findClass(name); } protected Class<?> loadClassPlugins(String name) { // remove this class loader as the context class loader // when loading classes from plug-ins...see bug 94471 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); if (fContextClassloader != null) { Thread.currentThread().setContextClassLoader(fContextClassloader); } try { Class<?> result = null; if (fPluginLoaders != null) { for (int i = 0; (i < fPluginLoaders.length) && (result == null); i++) { try { result = fPluginLoaders[i].loadClass(name); } catch (ClassNotFoundException e) { // Ignore exception now. If necessary we'll throw // a ClassNotFoundException in loadClass(String) } } } return result; } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } /* * @see java.net.URLClassLoader#findResource(java.lang.String) */ @Override public URL findResource(String name) { if (fAllowPluginLoading || !(name.startsWith(ANT_URL_PREFIX))) { URL result = findResourcePlugins(name); if (result != null) { return result; } } return super.findResource(name); } private URL findResourcePlugins(String name) { // remove this class loader as the context class loader // when loading resources from plug-ins...see bug 94471 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); if (fContextClassloader != null) { Thread.currentThread().setContextClassLoader(fContextClassloader); } try { URL result = null; if (fPluginLoaders != null) { for (int i = 0; i < fPluginLoaders.length; i++) { result = fPluginLoaders[i].getResource(name); if (result != null) { return result; } } } } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } return null; } /* * @see java.net.URLClassLoader#findResources(java.lang.String) */ @Override public Enumeration<URL> findResources(String name) throws IOException { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); if (fContextClassloader != null) { Thread.currentThread().setContextClassLoader(fContextClassloader); } ArrayList<URL> all = new ArrayList<>(); try { if (fAllowPluginLoading || !(name.startsWith(ANT_URL_PREFIX) || name.startsWith(ANT_URL_PREFIX, 1))) { if (fPluginLoaders != null) { Enumeration<URL> result = null; for (int i = 0; i < fPluginLoaders.length; i++) { result = fPluginLoaders[i].getResources(name); while (result.hasMoreElements()) { all.add(result.nextElement()); } } } } Enumeration<URL> superResources = super.findResources(name); if (all.isEmpty()) { return superResources; } while (superResources.hasMoreElements()) { all.add(superResources.nextElement()); } return Collections.enumeration(all); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } /** * Sets whether this class loader will allow Apache Ant classes or resources to be found or loaded from its set of plug-in class loaders. * * @param allowLoading * whether or not to allow the plug-in class loaders to load the Apache Ant classes or resources */ public void allowPluginClassLoadersToLoadAnt(boolean allowLoading) { fAllowPluginLoading = allowLoading; } public void setPluginContextClassloader(ClassLoader classLoader) { fContextClassloader = classLoader; } }