/*
* MicroJIAC - A Lightweight Agent Framework
* This file is part of MicroJIAC CDC-Launcher.
*
* Copyright (c) 2007-2012 DAI-Labor, Technische Universität Berlin
*
* This library includes software developed at DAI-Labor, Technische
* Universität Berlin (http://www.dai-labor.de)
*
* This library is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* $Id$
*/
package de.jiac.micro.cl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
/**
* @author Marcel Patzlaff
* @version $Revision$
*/
public class ContainerClassLoader extends ClassLoader implements ITransformingClassLoader {
private final ClassPath _classPath;
private final IClassTransformer _transformer;
private final ArrayList _loaderHierarchy;
public ContainerClassLoader(ClassPath classPath, ClassLoader parent, IClassTransformer transformer) {
super(parent);
_classPath = classPath;
_transformer= transformer;
_loaderHierarchy= new ArrayList();
for(ClassLoader current= this; current != null; current= current.getParent()) {
_loaderHierarchy.add(current);
}
}
public ContainerClassLoader(ClassPath classPath, ClassLoader parent) {
this(classPath, parent, null);
}
public ContainerClassLoader(ClassPath classPath) {
this(classPath, null, null);
}
public ClassPath getClassPath() {
return _classPath;
}
public final synchronized boolean isTransformerForClass(IClassTransformer transformer, String className) {
final String resourceName= className.replace('.', '/').concat(".class");
ClassLoader responsibleLoader= null;
for(int i= _loaderHierarchy.size() - 1; i >= 0; --i) {
ClassLoader loader= (ClassLoader) _loaderHierarchy.get(i);
if(loader.getResource(resourceName) != null) {
responsibleLoader= loader;
break;
}
}
if(responsibleLoader instanceof ITransformingClassLoader) {
return ((ITransformingClassLoader) responsibleLoader).hasTransformer(transformer);
}
return false;
}
public boolean hasTransformer(IClassTransformer transformer) {
return transformer != null && _transformer == transformer;
}
protected Class findClass(String name) throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
URL url;
try {
url= _classPath.findResource(path);
} catch (IOException ioe) {
throw new ClassNotFoundException(name, ioe);
}
if (url != null) {
try {
return defineClass(name, url);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
}
throw new ClassNotFoundException(name);
}
protected URL findResource(String name) {
try {
return _classPath.findResource(name);
} catch (IOException ioe) {
return null;
}
}
protected Enumeration findResources(String name) throws IOException {
return _classPath.findResources(name);
}
private Class defineClass(String name, URL url) throws IOException {
InputStream input= url.openStream();
if(input != null) {
ByteArrayOutputStream buffer= new ByteArrayOutputStream();
byte[] readBuffer= new byte[128];
for(int numBytes= 0; (numBytes= input.read(readBuffer)) > 0;) {
buffer.write(readBuffer, 0, numBytes);
}
int len= buffer.size();
byte[] classContent= buffer.toByteArray();
if(_transformer != null) {
classContent= _transformer.transformClass(this, classContent , 0, len);
len= classContent.length;
}
return defineClass(name, classContent, 0, len);
}
throw new IOException("could not open inputstream for " + url.toString());
}
}