package com.de22.javabytecode.code; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import com.common.debug.Debug; import com.common.io.ByteArrayInputStream; import com.common.io.ByteArrayOutputStream; import com.common.io.ObjectInputStream; import com.common.io.ObjectOutputStream; import com.de22.javabytecode.Type; /** * Copyright Declarative Engineering LLC 2007

* A simple test class that reads in a class file and then writes it out without any modifications. * This class tests the ability to read and write a class file without introducing errors. */ public class Test { /** * Reverse engineers a class file and writes it back out to 'output.class'. * @param args The array of initialization parameters. * args[0] = The path and file name of the class to reverse engineer. * args[1] = The path (must exist) where the output.class file will be stored. If the file exists it will be over written. */ public static void main(String[] args) { String debugText = null; long t = System.currentTimeMillis(); try { File file = new File(args[0]); File path = args.length > 1 ? new File(args[1]) : null; if(path != null && (path.isFile() || (!path.exists() && !path.mkdirs()))) { path = null; }//if// if(file.getName().endsWith(".class")) { debugText = file.getPath(); processClassFile(file, new File(path, "output.class")); compareClassFiles(file, new File(path, "output.class")); }//if// }//try// catch(Throwable e) { Debug.log(e, "Caught while processing the class file: " + debugText); }//catch// Debug.log("Total time (milliseconds): " + (System.currentTimeMillis() - t)); System.exit(0); }//main()// /** * Writes a file. * @param file The file to write. * @param bytes The bytes to place in the file. */ public static void writeFile(File file, byte[] bytes) { FileOutputStream fout = null; try { fout = new FileOutputStream(file); fout.write(bytes); }//try// catch(Throwable e) { e.printStackTrace(); }//catch// finally { if(fout != null) { try { fout.close(); }//try// catch(Throwable e) { }//catch// }//if// }//finally// }//writeFile()// /** * Reads a file and returns the bytes contained there in. * @param file The file to read. * @return The bytes contained in the file. */ public static byte[] readFile(File file) { FileInputStream fin = null; byte[] bytes = null; int counter = 0; try { fin = new FileInputStream(file); bytes = new byte[fin.available()]; while(counter < bytes.length) { counter += fin.read(bytes, counter, bytes.length - counter); }//while// fin.close(); }//try// catch(Throwable e) { e.printStackTrace(); }//catch// finally { if(fin != null) { try { fin.close(); }//try// catch(Throwable e) { }//catch// }//if// }//finally// return bytes; }//readFile()// /** * Processes a class file and writes out the byte codes in a semi-readable form. * @param bytesIn The input stream containing the bytes codes. This stream will always be closed by this method. * @param outputPath The optional path where the class output should be written to (under its packaging of course). The console will be used otherwise. */ private static void processClassFile(File inputFile, File outputFile) throws Throwable { ByteArrayInputStream bin = null; ObjectInputStream in = null; Type type = null; ByteArrayOutputStream bout = null; ObjectOutputStream out = null; try { bin = new ByteArrayInputStream(readFile(inputFile)); in = new ObjectInputStream(bin, null, null); type = new Type(); type.readExternal(in); bout = new ByteArrayOutputStream(100000, false); out = new ObjectOutputStream(bout, null); type.writeExternal(out); out.flush(); writeFile(outputFile, bout.toByteArray()); }//try// catch(Throwable e) { e.printStackTrace(); throw e; }//catch// }//processClassFile()// /** * Processes a class file and writes out the byte codes in a semi-readable form. * @param bytesIn The input stream containing the bytes codes. This stream will always be closed by this method. * @param outputPath The optional path where the class output should be written to (under its packaging of course). The console will be used otherwise. */ private static void compareClassFiles(File inputFile, File outputFile) throws Throwable { byte[] originalBytes; byte[] modifiedBytes; int byteLength; originalBytes = readFile(inputFile); modifiedBytes = readFile(outputFile); byteLength = Math.min(originalBytes.length, modifiedBytes.length); for(int index = 0; index < byteLength; index++) { if(originalBytes[index] != modifiedBytes[index]) { Debug.log("Files diverge at index " + index); return; }//if// }//for// if(originalBytes.length != modifiedBytes.length) { Debug.log("One file has more bytes than the other."); }//if// else { Debug.log("Files are exactly the same."); }//else// }//processClassFile()// }//Test//