001: /*
002: * FieldSig.java --
003: *
004: * This class implements the internal representation of a Java
005: * field signature.
006: *
007: * Copyright (c) 1997 Sun Microsystems, Inc.
008: *
009: * See the file "license.terms" for information on usage and
010: * redistribution of this file, and for a DISCLAIMER OF ALL
011: * WARRANTIES.
012: *
013: * RCS: @(#) $Id: FieldSig.java,v 1.9 2006/04/13 07:36:50 mdejong Exp $
014: *
015: */
016:
017: package tcl.lang;
018:
019: import tcl.lang.reflect.*;
020: import java.lang.reflect.*;
021: import java.util.*;
022:
023: /**
024: * This class implements the internal representation of a Java field
025: * signature.
026: */
027:
028: class FieldSig implements InternalRep {
029:
030: // The class that the field signature is used against. If the
031: // java::field command is given a class name, then the targetCls is
032: // that class; if If the java::field command is given a Java object,
033: // then the targetCls is the class of that object. targetCls is used
034: // to test the validity of a cached FieldSig internal rep.
035:
036: Class targetCls;
037:
038: // The class specified by the signature. If the signature only gives
039: // the name of a field and omits the declaring class, then sigCls is
040: // the same as targetCls.
041:
042: Class sigCls;
043:
044: // The handle to the field as given by the field signature.
045:
046: Field field;
047:
048: // The PkgInvoker used to access the field.
049:
050: PkgInvoker pkgInvoker;
051:
052: /*
053: *----------------------------------------------------------------------
054: *
055: * FieldSig --
056: *
057: * Creates a new FieldSig instance.
058: *
059: * Side effects:
060: * Member fields are initialized.
061: *
062: *----------------------------------------------------------------------
063: */
064:
065: FieldSig(Class tc, // Initial value for targetCls.
066: Class sc, // Initial value for sigCls.
067: PkgInvoker p, // Initial value for pkgInvoker.
068: Field f) // Initial value for field.
069: {
070: targetCls = tc;
071: sigCls = sc;
072: pkgInvoker = p;
073: field = f;
074: }
075:
076: /*
077: *----------------------------------------------------------------------
078: *
079: * duplicate --
080: *
081: * Make a copy of an object's internal representation.
082: *
083: * Results:
084: * Returns a newly allocated instance of the appropriate type.
085: *
086: * Side effects:
087: * None.
088: *
089: *----------------------------------------------------------------------
090: */
091:
092: public InternalRep duplicate() {
093: return new FieldSig(targetCls, sigCls, pkgInvoker, field);
094: }
095:
096: /**
097: * Implement this no-op for the InternalRep interface.
098: */
099:
100: public void dispose() {
101: }
102:
103: /*
104: *----------------------------------------------------------------------
105: *
106: * get --
107: *
108: * Returns the FieldSig internal rep given by the field signature.
109: *
110: * Results:
111: * The FieldSig given by the signature.
112: *
113: * Side effects:
114: * When successful, the internalRep of the signature object is
115: * converted to FieldSig.
116: *
117: *----------------------------------------------------------------------
118: */
119:
120: static FieldSig get(Interp interp, // Current interpreter
121: TclObject signature, // The TclObject that holds a field signature.
122: Class targetCls) // The target class of the field signature.
123: throws TclException // Standard Tcl exception.
124: {
125: InternalRep rep = signature.getInternalRep();
126:
127: if ((rep instanceof FieldSig)
128: && (((FieldSig) rep).targetCls == targetCls)) {
129: // The cached internal rep is a valid field signature for
130: // the given targetCls.
131:
132: return (FieldSig) rep;
133: }
134:
135: String fieldName;
136: TclObject sigClsObj;
137: Class sigCls;
138: Field field;
139:
140: int len = TclList.getLength(interp, signature);
141: if ((len < 1) || (len > 2)) {
142: throw new TclException(interp, "bad field signature \""
143: + signature + "\"");
144: }
145:
146: if (len == 1) {
147: fieldName = signature.toString();
148: sigClsObj = null;
149: } else {
150: fieldName = TclList.index(interp, signature, 0).toString();
151: sigClsObj = TclList.index(interp, signature, 1);
152: }
153:
154: if (sigClsObj != null) {
155: sigCls = ClassRep.get(interp, sigClsObj);
156: if (!sigCls.isAssignableFrom(targetCls)) {
157: throw new TclException(interp, "\""
158: + JavaInfoCmd.getNameFromClass(sigCls)
159: + "\" is not a superclass of \""
160: + JavaInfoCmd.getNameFromClass(targetCls)
161: + "\"");
162: }
163: if (!PkgInvoker.isAccessible(sigCls)) {
164: JavaInvoke.notAccessibleError(interp, sigCls);
165: }
166: } else {
167: sigCls = targetCls;
168: }
169:
170: try {
171: field = getAccessibleField(sigCls, fieldName);
172: } catch (NoSuchFieldException e) {
173: throw new TclException(interp, "no accessible field \""
174: + signature + "\" found in class "
175: + JavaInfoCmd.getNameFromClass(sigCls));
176: }
177:
178: FieldSig sig = new FieldSig(targetCls, sigCls, PkgInvoker
179: .getPkgInvoker(targetCls), field);
180: signature.setInternalRep(sig);
181:
182: return sig;
183: }
184:
185: /*
186: *----------------------------------------------------------------------
187: *
188: * getAccessibleFields --
189: *
190: * Returns all fields that can be read/written for a given class.
191: *
192: * Results:
193: * An array of all the accessible fields in the class.
194: *
195: * Side effects:
196: * None.
197: *
198: *----------------------------------------------------------------------
199: */
200:
201: static Field[] getAccessibleFields(Class cls) // The class to query.
202: {
203: if (PkgInvoker.usesDefaultInvoker(cls)) {
204: return cls.getFields();
205: } else {
206: Field[] fields = cls.getDeclaredFields();
207: ArrayList alist = null;
208: boolean skipped_any = false;
209:
210: for (int i = 0; i < fields.length; i++) {
211: Field f = fields[i];
212: if (PkgInvoker.isAccessible(f)) {
213: if (alist == null) {
214: alist = new ArrayList(fields.length);
215: }
216: alist.add(f);
217: } else {
218: skipped_any = true;
219: }
220: }
221:
222: if (skipped_any) {
223: fields = new Field[alist.size()];
224: for (int i = 0; i < fields.length; i++) {
225: fields[i] = (Field) alist.get(i);
226: }
227: }
228: return fields;
229: }
230: }
231:
232: /*
233: *----------------------------------------------------------------------
234: *
235: * getAccessibleField --
236: *
237: * Returns an accessible field given by the fieldName and
238: * the given class.
239: *
240: * Results:
241: * An accessible field in the class, raises a NoSuchFieldException
242: * if an accessible field cannot be found.
243: *
244: * Side effects:
245: * None.
246: *
247: *----------------------------------------------------------------------
248: */
249:
250: static Field getAccessibleField(Class cls, // The class to query.
251: String fieldName) // The field name.
252: throws NoSuchFieldException {
253: if (PkgInvoker.usesDefaultInvoker(cls)) {
254: return cls.getField(fieldName);
255: } else {
256: Field f = cls.getDeclaredField(fieldName);
257: if (!PkgInvoker.isAccessible(f)) {
258: throw new NoSuchFieldException();
259: }
260: return f;
261: }
262: }
263: } // end FieldSig
|