001: package gnu.kawa.reflect;
002:
003: import gnu.mapping.*;
004: import gnu.bytecode.*;
005: import gnu.mapping.Location; // As opposed to gnu.bytecode.Location.
006: import gnu.expr.*;
007:
008: /** A Location whose value is that of a named field/method of an object.
009: * The object is used as the owning Location's value.
010: * (For now, only fields are supported.)
011: */
012:
013: public class ClassMemberLocation extends Location {
014: Object instance;
015: ClassType type;
016: /** Member (method or field) name. */
017: String mname;
018: java.lang.reflect.Field rfield;
019:
020: public final Object getInstance() {
021: return instance;
022: }
023:
024: public final void setInstance(Object obj) {
025: instance = obj;
026: }
027:
028: public ClassMemberLocation(Object instance, ClassType type,
029: String mname) {
030: this .instance = instance;
031: this .type = type;
032: this .mname = mname;
033: }
034:
035: public ClassMemberLocation(Object instance, Class clas, String mname) {
036: this .instance = instance;
037: this .type = (ClassType) Type.make(clas);
038: this .mname = mname;
039: }
040:
041: public String getMemberName() {
042: return mname;
043: }
044:
045: public ClassType getDeclaringClass() {
046: return type;
047: }
048:
049: public ClassMemberLocation(Object instance,
050: java.lang.reflect.Field field) {
051: this .instance = instance;
052: this .rfield = field;
053: this .mname = field.getName();
054: }
055:
056: void setup() {
057: if (rfield == null) {
058: Class clas;
059: try {
060: clas = type.getReflectClass();
061: } catch (RuntimeException ex) {
062: RuntimeException uex = new UnboundLocationException(
063: null, "Unbound location - " + ex.toString());
064: /* #ifdef use:java.lang.Throwable.getCause */
065: uex.initCause(ex);
066: /* #endif */
067: throw uex;
068: }
069: try {
070: rfield = clas.getField(mname);
071: } catch (java.lang.NoSuchFieldException ex) {
072: RuntimeException uex = new UnboundLocationException(
073: null, "Unbound location " + " - no field "
074: + mname + " in " + type.getName());
075: /* #ifdef use:java.lang.Throwable.getCause */
076: uex.initCause(ex);
077: /* #endif */
078: throw uex;
079: }
080: }
081: }
082:
083: public java.lang.reflect.Field getRField() {
084: java.lang.reflect.Field rfld = this .rfield;
085: if (rfld == null) {
086: Class clas = null;
087: try {
088: clas = type.getReflectClass();
089: rfld = clas.getField(mname);
090: this .rfield = rfld;
091: } catch (Exception ex) {
092: return null;
093: }
094: }
095: return rfld;
096: }
097:
098: public Object get(Object defaultValue) {
099: java.lang.reflect.Field rfld = getRField();
100: if (rfld == null)
101: return defaultValue;
102:
103: try {
104: return rfld.get(instance);
105: } catch (IllegalAccessException ex) {
106: throw WrappedException.wrapIfNeeded(ex);
107: }
108: }
109:
110: public boolean isConstant() {
111: java.lang.reflect.Field rfld = getRField();
112: return rfld != null
113: && (rfield.getModifiers() & Access.FINAL) != 0;
114: }
115:
116: public boolean isBound() {
117: java.lang.reflect.Field rfld = getRField();
118: return rfld != null;
119: }
120:
121: public void set(Object value) {
122: setup();
123: try {
124: rfield.set(instance, value);
125: return;
126: } catch (IllegalAccessException ex) {
127: throw WrappedException.wrapIfNeeded(ex);
128: }
129: // This is a bit of a kludge FIXME.
130: //setLocation(loc, new TrivialLocation(getEnvironment(loc)));
131: //setValue(loc, value);
132: }
133:
134: public static void define(Object instance,
135: java.lang.reflect.Field rfield, String uri,
136: Language language, Environment env)
137: throws IllegalAccessException {
138: Object fvalue = rfield.get(instance);
139: Type ftype = Type.make(rfield.getType());
140: boolean isAlias = ftype.isSubtype(Compilation.typeLocation);
141: boolean isProcedure = ftype
142: .isSubtype(Compilation.typeProcedure);
143: Object fdname = ((fvalue instanceof Named && !isAlias) ? ((Named) fvalue)
144: .getSymbol()
145: : Compilation.demangleName(rfield.getName(), true));
146: Symbol sym;
147: if (fdname instanceof Symbol)
148: sym = (Symbol) fdname;
149: else {
150: sym = Symbol.make(uri == null ? "" : uri, fdname.toString()
151: .intern());
152: }
153: boolean isFinal = (rfield.getModifiers() & Access.FINAL) != 0;
154: Location loc;
155: Object property = null;
156: if (isAlias && isFinal) {
157: loc = (Location) fvalue;
158: } else {
159: if (isFinal)
160: property = language.getEnvPropertyFor(rfield, fvalue);
161: loc = new ClassMemberLocation(instance, rfield);
162: }
163: env.addLocation(sym, property, loc);
164: }
165:
166: /** Import all the public fields of an object. */
167: public static void defineAll(Object instance, Environment env)
168: throws IllegalAccessException {
169: Class clas = instance.getClass();
170: Language language = Language.getDefaultLanguage();
171: java.lang.reflect.Field[] fields = clas.getFields();
172: for (int i = fields.length; --i >= 0;) {
173: java.lang.reflect.Field field = fields[i];
174: String fname = field.getName();
175: if (fname.startsWith(Declaration.PRIVATE_PREFIX)
176: || fname.endsWith("$instance"))
177: continue;
178: define(instance, field, null, language, env);
179: }
180: }
181: }
|