* @throws TunnelException wraps a {@link IOException}
*/
protected Class findClass(String name) throws ClassNotFoundException {
// Check precompiled classes (classes that were parsed and compiled, but were not yet needed).
ClassFile cf = (ClassFile) this.precompiledClasses.get(name);
if (cf == null) {
// Check parsed, but uncompiled compilation units.
Java.CompilationUnit compilationUnitToCompile = null;
for (Iterator i = this.uncompiledCompilationUnits.iterator(); i.hasNext();) {
Java.CompilationUnit cu = (Java.CompilationUnit) i.next();
if (cu.findClass(name) != null) {
compilationUnitToCompile = cu;
break;
}
}
// Find and parse the right compilation unit.
if (compilationUnitToCompile == null) {
// Find and parse the right compilation unit, and add it to
// "this.uncompiledCompilationUnits".
if (this.iClassLoader.loadIClass(Descriptor.fromClassName(name)) == null) throw new ClassNotFoundException(name);
for (Iterator i = this.uncompiledCompilationUnits.iterator(); i.hasNext();) {
Java.CompilationUnit cu = (Java.CompilationUnit) i.next();
if (cu.findClass(name) != null) {
compilationUnitToCompile = cu;
break;
}
}
if (compilationUnitToCompile == null) throw new RuntimeException(); // SNO: Loading IClass does not parse the CU that defines the IClass.
}
// Compile the compilation unit.
ClassFile[] cfs;
try {
cfs = compilationUnitToCompile.compile(this.iClassLoader, this.debuggingInformation);
} catch (Java.CompileException e) {
throw new TunnelException(e);
}
// Now that the CU is compiled, remove it from the set of uncompiled CUs.
this.uncompiledCompilationUnits.remove(compilationUnitToCompile);
// Get the generated class file.
for (int i = 0; i < cfs.length; ++i) {
if (cfs[i].getThisClassName().equals(name)) {
if (cf != null) throw new RuntimeException(); // SNO: Multiple CFs with the same name.
cf = cfs[i];
} else {
if (this.precompiledClasses.containsKey(cfs[i].getThisClassName())) throw new TunnelException(new Java.CompileException("Class or interface \"" + name + "\" is defined in more than one compilation unit", null));
this.precompiledClasses.put(cfs[i].getThisClassName(), cfs[i]);
}
}
if (cf == null) throw new RuntimeException(); // SNO: Compilation of CU does not generate CF with requested name.
}
if (cf == null) throw new ClassNotFoundException(name);
// Store the class file's byte code into a byte array.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
cf.store(bos);
} catch (IOException ex) {
throw new RuntimeException(); // SNO: ByteArrayOutputStream thows IOException,
}
byte[] ba = bos.toByteArray();