/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.openejb.server.cxf.transport.util;
import org.apache.openejb.util.classloader.Unwrappable;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
public class CxfContainerClassLoader extends ClassLoader implements Unwrappable {
private static final ClassLoader CONTAINER_LOADER = CxfUtil.class.getClassLoader();
public static final String CXF_PACKAGE = "org.apache.cxf.";
private final ThreadLocal<ClassLoader> tccl = new ThreadLocal<ClassLoader>();
public CxfContainerClassLoader() {
super(CONTAINER_LOADER);
}
public void tccl(final ClassLoader loader) {
if (loader != this) { // otherwise it will end up with infinite loops
tccl.set(loader);
}
}
public void clear() {
tccl.remove();
}
public boolean hasTccl() {
final ClassLoader current = tccl.get();
if (current != null) {
return true;
}
tccl.remove();
return false;
}
private ClassLoader tccl() {
final ClassLoader current = tccl.get();
if (current != null) {
return current;
} else {
tccl.remove();
}
return CONTAINER_LOADER;
}
@Override
protected Class<?> findClass(final String name) throws ClassNotFoundException {
if (name.startsWith(CXF_PACKAGE)) {
Throwable th = new ClassNotFoundException(name);
try {
return CONTAINER_LOADER.loadClass(name);
} catch (final Exception e) {
th = e;
} catch (final Error err) {
th = err;
}
// some additional cxf classes can be provided by apps
try {
return tccl().loadClass(name);
} catch (final Exception | Error e) {
// no-op: try tccl
}
// if we are here we were not able to load the class from the container
// so throw the first exception
if (Error.class.isInstance(th)) {
throw Error.class.cast(th);
}
if (ClassNotFoundException.class.isInstance(th)) {
throw ClassNotFoundException.class.cast(th);
}
throw new ClassNotFoundException(th.getMessage(), th);
}
return tccl().loadClass(name);
}
@Override
protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
final Class<?> clazz = findClass(name);
if (resolve) {
resolveClass(clazz);
}
return clazz;
}
@Override
protected URL findResource(final String name) {
return tccl().getResource(name);
}
@Override
protected Enumeration<URL> findResources(final String name) throws IOException {
return tccl().getResources(name);
}
@Override
public boolean equals(final Object o) {
final ClassLoader classLoader = tccl();
if (classLoader == null || CxfContainerClassLoader.class.isInstance(classLoader)) { // avoid loop
return CONTAINER_LOADER.equals(o);
}
return classLoader.equals(o);
}
@Override
public int hashCode() {
final ClassLoader classLoader = tccl();
if (classLoader == null || CxfContainerClassLoader.class.isInstance(classLoader)) { // avoid loop
return CONTAINER_LOADER.hashCode();
}
return classLoader.hashCode();
}
@Override
public ClassLoader unwrap() {
return tccl();
}
}