/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.module.embedded.internal.classloading;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.Boolean.valueOf;
import static java.lang.String.format;
import static java.lang.System.getProperty;
import static java.util.Collections.emptyList;
import org.mule.runtime.module.embedded.internal.NotExportedClassException;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// TODO MULE-11882 - Consolidate classloading isolation
public class FilteringClassLoader extends ClassLoader {
protected static final Logger logger = LoggerFactory.getLogger(FilteringClassLoader.class);
public static final String SYSTEM_PROPERTY_PREFIX = "mule.";
public static final String MULE_LOG_VERBOSE_CLASSLOADING = SYSTEM_PROPERTY_PREFIX + "classloading.verbose";
private final ClassLoaderFilter filter;
/**
* Creates a new filtering classLoader
*
* @param filter filters access to classes and resources from the artifact classLoader. Non null
*/
public FilteringClassLoader(ClassLoaderFilter filter) {
checkArgument(filter != null, "Filter cannot be null");
this.filter = filter;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (filter.exportsClass(name)) {
return super.loadClass(name);
} else {
throw new NotExportedClassException(name, filter);
}
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (filter.exportsClass(name)) {
return super.loadClass(name, resolve);
} else {
throw new NotExportedClassException(name, filter);
}
}
@Override
public URL getResource(String name) {
if (filter.exportsResource(name)) {
return getResourceFromDelegate(name);
} else {
logClassloadingTrace(format("Resource '%s' not found in classloader", name));
logClassloadingTrace(format("Filter applied for resource '%s'", name));
return null;
}
}
protected URL getResourceFromDelegate(String name) {
return findResource(name);
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if (filter.exportsResource(name)) {
return getResourcesFromDelegate(name);
} else {
logClassloadingTrace(format("Resources '%s' not found in classloader.", name));
logClassloadingTrace(format("Filter applied for resources '%s'", name));
return new EnumerationAdapter<>(emptyList());
}
}
private void logClassloadingTrace(String message) {
if (isVerboseClassLoading()) {
logger.info(message);
} else if (logger.isTraceEnabled()) {
logger.trace(message);
}
}
private Boolean isVerboseClassLoading() {
return valueOf(getProperty(MULE_LOG_VERBOSE_CLASSLOADING));
}
protected Enumeration<URL> getResourcesFromDelegate(String name) throws IOException {
return findResources(name);
}
}