Files
Brainstorm/Class File Services/src/com/de22/javabytecode/code/Test.java

170 lines
4.9 KiB
Java
Raw Normal View History

2014-05-30 10:31:51 -07:00
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<p>
* 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//