01: /*
02: * Licensed to the Apache Software Foundation (ASF) under one or more
03: * contributor license agreements. See the NOTICE file distributed with
04: * this work for additional information regarding copyright ownership.
05: * The ASF licenses this file to You under the Apache License, Version 2.0
06: * (the "License"); you may not use this file except in compliance with
07: * the License. You may obtain a copy of the License at
08: *
09: * http://www.apache.org/licenses/LICENSE-2.0
10: *
11: * Unless required by applicable law or agreed to in writing, software
12: * distributed under the License is distributed on an "AS IS" BASIS,
13: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14: * See the License for the specific language governing permissions and
15: * limitations under the License.
16: */
17:
18: package org.apache.commons.beanutils.converters;
19:
20: import java.io.InputStream;
21: import java.io.ByteArrayOutputStream;
22: import java.io.FileNotFoundException;
23: import java.io.IOException;
24:
25: /**
26: * A special classloader useful for testing j2ee-like scenarios.
27: *
28: * <p>In some tests we want to be able to emulate "container" frameworks,
29: * where code runs in a hierarchy of classloaders, and certain classes may
30: * be loaded by various classloaders in the hierarchy.</p>
31: *
32: * <p>Normally this is done by having certain jars or class-file-directories
33: * in the classpath of some classloaders but not others. This is quite
34: * difficult difficult to integrate with the build process for the unit
35: * tests though; compiling certain classes and having the output go into
36: * places that is not in the default classpath for the unit tests would be
37: * a major pain.</p>
38: *
39: * <p>So this class takes a sneaky alternative approach: it can grab any class
40: * already loaded by a parent classloader and <i>reload</i> that class via this
41: * classloader. The effect is exactly as if a class (or jar file) had been
42: * present in the classpath for a container's "shared" classloader <i>and</i>
43: * been present in the component-specific classpath too, without any messing
44: * about with the way unit test code is compiled or executed.
45: */
46:
47: public class ClassReloader extends ClassLoader {
48: public ClassReloader(ClassLoader parent) {
49: super (parent);
50: }
51:
52: /**
53: * Given a class already in the classpath of a parent classloader,
54: * reload that class via this classloader.
55: */
56: public Class reload(Class clazz) throws FileNotFoundException,
57: IOException {
58: String className = clazz.getName();
59: String classFile = className.replace('.', '/') + ".class";
60: InputStream classStream = getParent().getResourceAsStream(
61: classFile);
62:
63: if (classStream == null) {
64: throw new FileNotFoundException(classFile);
65: }
66:
67: byte[] buf = new byte[1024];
68: ByteArrayOutputStream baos = new ByteArrayOutputStream();
69: for (;;) {
70: int bytesRead = classStream.read(buf);
71: if (bytesRead == -1)
72: break;
73: baos.write(buf, 0, bytesRead);
74: }
75: classStream.close();
76:
77: byte[] classData = baos.toByteArray();
78:
79: // now we have the raw class data, let's turn it into a class
80: Class newClass = defineClass(className, classData, 0,
81: classData.length);
82: resolveClass(newClass);
83: return newClass;
84: }
85: }
|