001: package jsint;
002:
003: /** A DynamicVariable represents a global value in a particular
004: * environment. **/
005:
006: public class DynamicVariable implements java.io.Serializable {
007:
008: Symbol name;
009: Object value = U.UNDEFINED;
010:
011: public DynamicVariable(Symbol name) {
012: this .name = name;
013: }
014:
015: public boolean isDefined() {
016: return value != U.UNDEFINED;
017: }
018:
019: public Object getDynamicValue() {
020: Object value = this .value;
021: /** You may be naming a Java dot item but not have a value yet. **/
022: if (value == U.UNDEFINED) {
023: value = lookupJavaBinding(name);
024: if (value != null)
025: this .value = value;
026: }
027: if (value == U.UNDEFINED)
028: return E
029: .error("ERROR: undefined variable \"" + name + "\"");
030: else if ((value instanceof JavaField)
031: && ((JavaField) value).isStatic)
032: return ((JavaField) value).apply(U.NO_ARGS);
033: else
034: return value;
035: }
036:
037: public Object setDynamicValue(Object newval) {
038: /** Look at the existing value to see if it is static field we
039: * should set. **/
040: Object existingValue = this .value;
041: if (existingValue == U.UNDEFINED) {
042: Object tmpValue = lookupJavaBinding(name);
043: if (tmpValue != null) {
044: this .value = tmpValue;
045: existingValue = tmpValue;
046: }
047: }
048: /** If you are a static field set the value there. **/
049: if ((existingValue instanceof JavaField)
050: && ((JavaField) existingValue).isStatic)
051: ((JavaField) existingValue).apply(new Object[] { newval });
052: else
053: this .value = newval;
054: return newval;
055: }
056:
057: /** Look like a symbol so (describe) can show procedures easily **/
058: public String toString() {
059: return name.toString();
060: }
061:
062: private void writeObject(java.io.ObjectOutputStream out)
063: throws java.io.IOException {
064: out.writeObject(name);
065: /** Toby Allsop: Use value rather than getDynamicValue() so you
066: can serialize code that has java dot of a class that doesn't
067: exist yet. **/
068: out.writeObject(value);
069: }
070:
071: private void readObject(java.io.ObjectInputStream in)
072: throws java.io.IOException, ClassNotFoundException {
073: name = (Symbol) in.readObject();
074: value = in.readObject();
075: }
076:
077: /** When deserialized, add yourself to the interaction environment
078: * and give it a value if you have one.
079: **/
080: private Object readResolve() throws java.io.ObjectStreamException {
081: DynamicVariable it = Scheme.getInteractionEnvironment().intern(
082: name);
083: if (value != U.UNDEFINED)
084: it.value = value;
085: return it;
086: }
087:
088: /** If var is a Java Literal, then return its value as a
089: method/constructor/field object otherwise return null **/
090: private static Object lookupJavaBinding(Symbol var) {
091: String fullname = var.toString();
092: String name = fullname;
093: boolean canAccessPrivateData = false;
094: if (fullname.endsWith("#")) {
095: canAccessPrivateData = true;
096: name = fullname.substring(0, name.length() - 1);
097: }
098: int firstIndex = name.indexOf('.');
099: int lastIndex = name.lastIndexOf('.');
100: int fieldIndex = name.lastIndexOf('$');
101: int nameLength = name.length();
102:
103: Object value = U.UNDEFINED;
104:
105: if (firstIndex == -1) {
106: return value; // symbol is not a Java Literal
107: }
108: try {
109: if (fieldIndex == nameLength - 1) {
110: if (firstIndex == 0) {
111: if (lastIndex > 0) { // ".CLASS.NAME$"
112: value = (new JavaField(name.substring(
113: lastIndex + 1, nameLength - 1), Import
114: .classNamed(name
115: .substring(1, lastIndex)),
116: canAccessPrivateData));
117: } else { // ".NAME$"
118: value = (new JavaField(name.substring(1,
119: nameLength - 1), null,
120: canAccessPrivateData));
121: }
122: } else { // "CLASS.NAME$"
123: value = (new JavaField(name.substring(
124: lastIndex + 1, nameLength - 1), Import
125: .classNamed(name.substring(0, lastIndex)),
126: canAccessPrivateData));
127:
128: }
129: } else if (firstIndex == 0) {
130: if (nameLength == 1)
131: return var; // "."
132: else if (lastIndex > 0) // ".CLASS.NAME"
133: value = (new JavaMethod(name.substring(
134: lastIndex + 1, nameLength), Import
135: .classNamed(name.substring(1, lastIndex)),
136: false, canAccessPrivateData));
137: else
138: value = (new JavaMethod(name.substring(1,
139: nameLength), null, false,
140: canAccessPrivateData));
141: } else if (lastIndex == nameLength - 1) // "CLASS."
142: value = (new JavaConstructor(Import.classNamed(
143: name.substring(0, lastIndex)).getName(),
144: canAccessPrivateData));
145: else {
146: String methodName = name.substring(lastIndex + 1,
147: nameLength);
148: if ("class".equals(methodName)) // "CLASS.class" class literal
149: value = (Import.classNamed(name.substring(0,
150: lastIndex)));
151: else
152: value = // "CLASS.NAME"
153: (new JavaMethod(name.substring(lastIndex + 1,
154: nameLength), Import.classNamed(name
155: .substring(0, lastIndex)), true,
156: canAccessPrivateData));
157: }
158: return value;
159: } catch (Exception e) {
160: if (DynamicEnvironment.showJavaDotWarnings)
161: Scheme.currentEvaluator().getError().println(
162: "Javadot WARNING: " + e.getMessage());
163:
164: return value;
165: }
166: }
167: }
|