001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.aspectwerkz.hook;
005:
006: import java.io.BufferedOutputStream;
007: import java.io.ByteArrayOutputStream;
008: import java.io.DataOutputStream;
009: import java.io.File;
010: import java.io.FileOutputStream;
011: import java.io.IOException;
012: import java.io.InputStream;
013:
014: /**
015: * Utility methods to manipulate class redefinition of java.lang.ClassLoader in xxxStarter
016: *
017: * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
018: */
019: public class ClassLoaderPatcher {
020: /**
021: * Converts an input stream to a byte[]
022: */
023: public static byte[] inputStreamToByteArray(InputStream is)
024: throws IOException {
025: ByteArrayOutputStream os = new ByteArrayOutputStream();
026: for (int b = is.read(); b != -1; b = is.read()) {
027: os.write(b);
028: }
029: return os.toByteArray();
030: }
031:
032: /**
033: * Gets the bytecode of the modified java.lang.ClassLoader using given ClassLoaderPreProcessor class name
034: */
035: static byte[] getPatchedClassLoader(String preProcessorName) {
036: byte[] abyte = null;
037: InputStream is = null;
038: try {
039: is = ClassLoader.getSystemClassLoader().getParent()
040: .getResourceAsStream("java/lang/ClassLoader.class");
041: abyte = inputStreamToByteArray(is);
042: } catch (IOException e) {
043: throw new Error("failed to read java.lang.ClassLoader: "
044: + e.toString());
045: } finally {
046: try {
047: is.close();
048: } catch (Exception e) {
049: ;
050: }
051: }
052: if (preProcessorName != null) {
053: try {
054: ClassLoaderPreProcessor clpi = (ClassLoaderPreProcessor) Class
055: .forName(preProcessorName).newInstance();
056: abyte = clpi.preProcess(abyte);
057: } catch (Exception e) {
058: System.err
059: .println("failed to instrument java.lang.ClassLoader: preprocessor not found");
060: e.printStackTrace();
061: }
062: }
063: return abyte;
064: }
065:
066: /**
067: * Dump bytecode bytes in dir/className.class directory, created if needed
068: */
069: private static void writeClass(String className, byte[] bytes,
070: String dir) {
071: String filename = dir + File.separatorChar
072: + className.replace('.', File.separatorChar) + ".class";
073: int pos = filename.lastIndexOf(File.separatorChar);
074: if (pos > 0) {
075: String finalDir = filename.substring(0, pos);
076: (new File(finalDir)).mkdirs();
077: }
078: try {
079: DataOutputStream out = new DataOutputStream(
080: new BufferedOutputStream(new FileOutputStream(
081: filename)));
082: out.write(bytes);
083: out.close();
084: } catch (IOException e) {
085: System.err.println("failed to write " + className + " in "
086: + dir);
087: e.printStackTrace();
088: }
089: }
090:
091: /**
092: * Patch java.lang.ClassLoader with preProcessorName instance and dump class bytecode in dir
093: */
094: public static void patchClassLoader(String preProcessorName,
095: String dir) {
096: byte[] cl = getPatchedClassLoader(preProcessorName);
097: writeClass("java.lang.ClassLoader", cl, dir);
098: }
099:
100: }
|