blob: baec66c1ba92ff4e2371502284f3265ee35af116 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2013 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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;
}
@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);
}
}
@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 (ClassLoader loader : fPluginLoaders) {
result = loader.getResource(name);
if (result != null) {
return result;
}
}
}
}
finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
return null;
}
@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 (ClassLoader loader : fPluginLoaders) {
result = loader.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;
}
}