Using the IBM article mentioned above I was able to get my code to go quite a
long way using introspection. It may still be useful to have better access to
this via the javassist api, as that would remove the need for introspection.
I'll report further on any problems I come across...
| package com.sun.labs.rdf.sommer;
|
| import com.sun.labs.rdf.annotations.RDF;
| import javassist.*;
| import javassist.expr.ExprEditor;
| import javassist.expr.FieldAccess;
|
| import java.lang.reflect.ParameterizedType;
| import java.lang.reflect.Type;
| import java.lang.reflect.TypeVariable;
|
| /**
| * @author Henry Story
| */
| public class ClassRewriter {
|
| public static String reverse(String value) {
| int length = value.length();
| StringBuffer buff = new StringBuffer(length);
| for (int i = length - 1; i >= 0; i--) {
| buff.append(value.charAt(i));
| }
| System.out.println("TranslateEditor.reverse returning " + buff);
| return buff.toString();
| }
|
| public static Object setField(Type gtype, Class c, Object o, String
url, Object value) {
| if (gtype instanceof ParameterizedType) {
|
| // list the raw type information
| ParameterizedType ptype = (ParameterizedType) gtype;
| Type rtype = ptype.getRawType();
| System.out.println("rawType is instance of " +
| rtype.getClass().getName());
| System.out.println(" (" + rtype + ")");
|
| // list the actual type arguments
| Type[] targs = ptype.getActualTypeArguments();
| System.out.println("actual type arguments are:");
| for (int j = 0; j < targs.length; j++) {
| System.out.println(" instance of " +
| targs[j].getClass().getName() + ":");
| System.out.println(" (" + targs[j] + ")");
| }
| } else {
| System.out.println
| ("getGenericType is not a ParameterizedType!");
| }
| if (c.getTypeParameters().length > 0) {
| System.out.println(c + "has " + c.getTypeParameters().length +
" type parameters");
| for (TypeVariable tv : c.getTypeParameters()) {
| System.out.println("t.name=" + tv.getName() + " t.gd=" +
tv.getGenericDeclaration());
| }
| }
| System.out.println("class=" + c + " setting o=" + o + " R=" + url +
" v=" + value);
| return value;
| }
|
|
| public static void getField(Class c, Object o, String url, Object
value) {
| System.out.println("class=" + c + " getting o=" + o + " R=" + url +
" v=" + value);
| }
|
|
| public static void main(String[] args) {
| if (args.length != 0) {
| try {
| // set up class loader with translator
| EditorTranslator xtor = new EditorTranslator(new
FieldSetEditor());
| ClassPool pool = ClassPool.getDefault();
| Loader loader = new Loader();
| loader.addTranslator(pool, xtor);
|
| // invoke the "main" method of the application class
|
| loader.run(args);
| } catch (Throwable ex) {
| ex.printStackTrace();
| }
| } else {
| System.out.println("Usage: ClassRewriter main-class args...");
| }
| }
|
|
| }
|
| class EditorTranslator implements Translator {
| private ExprEditor m_editor;
|
| EditorTranslator(ExprEditor editor) {
| m_editor = editor;
| }
|
| public void start(ClassPool pool) {
| System.out.println("start pool");
| }
|
|
| public void onLoad(ClassPool pool, String cname)
| throws NotFoundException, CannotCompileException {
| System.out.println("cname(in Onload)=" + cname);
| CtClass clas = pool.get(cname);
| clas.instrument(m_editor);
| }
| }
|
| class FieldSetEditor extends ExprEditor {
|
| FieldSetEditor() {
| }
|
| public void edit(FieldAccess arg) throws CannotCompileException {
| System.out.println("in edit- field=" + arg.getFieldName());
| try {
| String field;
| if ((field = containsRDF(arg.getField().getAnnotations())) !=
null) {
| if (arg.isWriter()) {
| StringBuffer code = new StringBuffer();
| code.append("$0.");
| code.append(arg.getFieldName());
| //
code.append("=com.sun.labs.rdf.sommer.ClassRewriter.reverse($1);");
| code.append("=(" + arg.getField().getType().getName() +
")"