001: /*
002: * FieldAccessorGenerator.java
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution of
007: * this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.compiler;
010:
011: import org.pnuts.util.*;
012: import org.pnuts.lang.Signature;
013: import java.lang.reflect.*;
014: import java.io.*;
015:
016: class FieldAccessorGenerator {
017:
018: static FieldAccessor generate(String fieldName, Class cls,
019: CodeLoader loader, boolean isStatic)
020: throws NoSuchFieldException, InstantiationException,
021: IOException, IllegalAccessException {
022: String tempClassName = "_" + (loader.nextCount() & 0x7fffffff);
023: ClassFile cf = new ClassFile(tempClassName,
024: "pnuts.compiler.FieldAccessor", null,
025: (short) (Constants.ACC_PUBLIC | Constants.ACC_FINAL));
026: Field field = cls.getField(fieldName);
027: Class type = field.getType();
028: String param = Signature.makeSignature(type);
029:
030: cf.openMethod("<init>", "()V", Constants.ACC_PUBLIC);
031: cf.add(Opcode.ALOAD_0);
032: cf.add(Opcode.INVOKESPECIAL, "pnuts.compiler.FieldAccessor",
033: "<init>", "()", "V");
034: cf.add(Opcode.RETURN);
035: cf.closeMethod();
036:
037: cf.openMethod("get", "(Ljava/lang/Object;)Ljava/lang/Object;",
038: Constants.ACC_PUBLIC);
039: if (type.isPrimitive()) {
040: cf.add(Opcode.NEW, DynamicProxyFactory.wrapperClass(type));
041: cf.add(Opcode.DUP);
042: if (isStatic) {
043: cf.add(Opcode.GETSTATIC, cls.getName(), fieldName,
044: param);
045: } else {
046: cf.add(Opcode.ALOAD_1);
047: if (!cls.equals(Object.class)) {
048: cf.add(Opcode.CHECKCAST, cls.getName());
049: }
050: cf
051: .add(Opcode.GETFIELD, cls.getName(), fieldName,
052: param);
053: }
054: cf.add(Opcode.INVOKESPECIAL, DynamicProxyFactory
055: .wrapperClass(type), "<init>", "("
056: + ClassFile.signature(type) + ")", "V");
057: } else {
058: if (isStatic) {
059: cf.add(Opcode.GETSTATIC, cls.getName(), fieldName,
060: param);
061: } else {
062: cf.add(Opcode.ALOAD_1);
063: if (!cls.equals(Object.class)) {
064: cf.add(Opcode.CHECKCAST, cls.getName());
065: }
066: cf
067: .add(Opcode.GETFIELD, cls.getName(), fieldName,
068: param);
069: }
070: }
071: cf.add(Opcode.ARETURN);
072: cf.closeMethod();
073:
074: cf.openMethod("set", "(Ljava/lang/Object;Ljava/lang/Object;)V",
075: Constants.ACC_PUBLIC);
076:
077: if (isStatic) {
078: cf.add(Opcode.ALOAD_1);
079: if (type.isPrimitive()) {
080: DynamicProxyFactory.castParam(cf, type);
081: } else {
082: cf.add(Opcode.CHECKCAST, type.getName());
083: }
084: cf.add(Opcode.PUTSTATIC, cls.getName(), fieldName, param);
085: } else {
086: cf.add(Opcode.ALOAD_1);
087: if (!cls.equals(Object.class)) {
088: cf.add(Opcode.CHECKCAST, cls.getName());
089: }
090: cf.add(Opcode.ALOAD_2);
091: if (type.isPrimitive()) {
092: DynamicProxyFactory.castParam(cf, type);
093: } else {
094: cf.add(Opcode.CHECKCAST, type.getName());
095: }
096: cf.add(Opcode.PUTFIELD, cls.getName(), fieldName, param);
097: }
098: cf.add(Opcode.RETURN);
099: cf.closeMethod();
100:
101: ByteArrayOutputStream bout = new ByteArrayOutputStream();
102: DataOutputStream dout = new DataOutputStream(bout);
103: cf.write(dout);
104:
105: /*debug(cf);*/
106:
107: Class clazz = loader.define(tempClassName, bout.toByteArray(),
108: 0, bout.size());
109: loader.resolve(clazz);
110: return (FieldAccessor) clazz.newInstance();
111: }
112:
113: /**
114: static void debug(ClassFile file) {
115: try {
116: String fileName = "/tmp/" + file.getClassName() + ".class";
117: System.out.println(fileName);
118: FileOutputStream fout = new FileOutputStream(fileName);
119: DataOutputStream dout = new DataOutputStream(fout);
120: file.write(dout);
121: fout.close();
122: } catch (IOException e) {
123: e.printStackTrace();
124: }
125: }
126: **/
127: }
|