Initial commit from SVN.

This commit is contained in:
wcrisman
2014-05-30 10:31:51 -07:00
commit b45e56b890
1968 changed files with 370949 additions and 0 deletions

View File

@@ -0,0 +1,205 @@
package com.de22.javabytecode.generator;
import java.io.IOException;
import java.lang.reflect.Modifier;
import com.common.io.*;
import com.common.debug.*;
import com.de22.javabytecode.*;
import com.de22.javabytecode.code.*;
/**
* Copyright Declarative Engineering LLC 1999<p>
* Provides some assistance methods for generating a class.
*/
public abstract class ClassGenerator {
public static final String INIT_METHOD_NAME = "<init>";
//private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
protected StringBuffer sharedBuffer = new StringBuffer(500); //A shared string buffer that can be used by the class generator and subclasses to temporarily buffer data within the method. Warning: This is reused by many methods so make sure you don't store anything important before calling another method.//
private Type type = null;
/**
* ClassGenerator constructor.
*/
private ClassGenerator() {
super();
}//ClassGenerator()//
/**
* ClassGenerator constructor.
*/
public ClassGenerator(String qualifiedClassName) {
super();
createClass(qualifiedClassName);
}//ClassGenerator()//
/**
* Creates a new type. All subsequent operations are against this type.
* <p>TODO: Provide more input to this method to allow different access flags and such.
* @param qualifiedClassName The fully qualified class name of this new class. Must use '/' instead of '.' & do not use a '.class' or '.java' extention.
*/
protected void createClass(String qualifiedClassName) {
try {
Type type = new Type(qualifiedClassName);
type.setAccessFlags((short) (Type.ACC_PUBLIC | Type.ACC_SUPER));
type.setMajorVersion((short) 45);
type.setMinorVersion((short) 3);
setType(type);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//createClass()//
/**
* Creates the one and only init method which should at the very least call the super classes' init method.
* <p>TODO: Stop ignoring the passed byte codes and instead add them in the mix.
* @param superClass The class that this class will inherit from.
* @param code This parameter is currently ignored.
*/
public void createInitMethod(Class superClass, byte[] code) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream(20, false);
StandardOutputStream out = new StandardOutputStream(bout);
short superInitIndex = getType().addConstantMethod(superClass, null, INIT_METHOD_NAME, new Class[0]);
out.writeByte((byte) 42); //aload_0
out.writeByte((byte) 183); //invokespecial -> invoke super class' <init> method.
out.writeShort((short) superInitIndex);
out.writeByte((byte) 177); //return
//Add the method to the type.//
getType().addMethod(Modifier.PUBLIC, null, INIT_METHOD_NAME, new Class[0], bout.toByteArray(), 1, 1);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//createInitMethod()//
/**
* Formats a descriptor string using the parameters and return type of the method.
* This is used to create method descriptors for a class file.
* <p>Example: void methodName(double[] a, String b) -> ([DLjava/lang/String;)V;
* @param returnType The descriptor's return type.
* @param parameterTypes The descriptor's parameter types (in order of parameter).
* @return The formatted type string.
*/
protected String formatDescriptor(Class returnType, Class[] parameterTypes) {
sharedBuffer.setLength(0);
FormatSupport.formatDescriptor(returnType, parameterTypes, sharedBuffer);
return sharedBuffer.toString();
}//formatDescriptor()//
/**
* Formats a non-primitive class to a class file compatible string.
* <p>NOTE: This method will not place an "L" at the beginning or a ";" at the end of the formatted string.
* @param type The non-primitive class to convert to a string.
* @return The string representation of the type.
*/
protected String formatNonPrimitiveType(String qualifiedTypeName) {
sharedBuffer.setLength(0);
FormatSupport.formatNonPrimitiveType(qualifiedTypeName, sharedBuffer);
return sharedBuffer.toString();
}//formatNonPrimitiveType()//
/**
* Formats a class to a class file compatible string.
* @param type The class to convert to a string.
* @return The formatted type string.
*/
protected String formatType(Class type) {
sharedBuffer.setLength(0);
FormatSupport.formatType(type, sharedBuffer);
return sharedBuffer.toString();
}//formatType()//
/**
* Generates a method signature string from the method.
* @param method The method whose signature should be generated.
*/
protected static String generateMethodSignature(java.lang.reflect.Method method) {
try {
StringBuffer signature = new StringBuffer(100);
Class[] parameterTypes = method.getParameterTypes();
for(int index = 0; index < parameterTypes.length; index++) {
if(signature == null) {
signature = new StringBuffer(100);
}//if//
else {
signature.append(',');
signature.append(' ');
}//else//
signature.append(parameterTypes[index].getName());
}//for//
signature.append('(');
if(signature != null) {
signature.append(signature);
}//if//
signature.append(')');
return signature.toString();
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
return "";
}//catch//
}//generateMethodSignature()//
/**
* Gets the classes' byte codes.
* @return The array of byte codes for the class.
*/
public byte[] getClassByteCodes() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(1000, false);
getType().writeExternal(new ObjectOutputStream(out, null));
return out.toByteArray();
}//getClassByteCodes()//
/**
* Gets the classes' type object.
* @return The type object describing the class byte codes.
*/
public Type getType() {
return type;
}//getType()//
/**
* Sets the classes' source file reference.
* <p>TODO: Implement this properly by adding an addAttributeSourceFile method to the Type class.
* @param path The path to the source file that created this class.
*/
public void setSourceFile(String path) {
try {
//Type type = getType();
//SourceFile sourceFile = new SourceFile(type, path);
//Add the attribute to the class.//
//type.addAttribute(sourceFile);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//setSuperClass()//
/**
* Sets the super class for this class.
* @param qualifiedSuperClassName The qualified class name of the super class. This string will be reformatted for use in the class byte codes.
*/
public void setSuperClass(String qualifiedSuperClassName) {
Type type = getType();
type.setSuperClass(formatNonPrimitiveType(qualifiedSuperClassName));
}//setSuperClass()//
/**
* Sets the classes' type object.
* @param type The type object describing the class byte codes.
*/
private void setType(Type type) {
this.type = type;
}//setType()//
}//ClassGenerator//