001: /*
002: * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.java;
027:
028: import sun.tools.tree.*;
029: import java.util.Vector;
030: import java.util.Hashtable;
031: import java.io.IOException;
032: import java.io.DataInputStream;
033: import java.io.ByteArrayInputStream;
034:
035: /**
036: * This class represents a binary member
037: *
038: * WARNING: The contents of this source file are not part of any
039: * supported API. Code that depends on them does so at its own risk:
040: * they are subject to change or removal without notice.
041: */
042: public final class BinaryMember extends MemberDefinition {
043: Expression value;
044: BinaryAttribute atts;
045:
046: /**
047: * Constructor
048: */
049: public BinaryMember(ClassDefinition clazz, int modifiers,
050: Type type, Identifier name, BinaryAttribute atts) {
051: super (0, clazz, modifiers, type, name, null, null);
052: this .atts = atts;
053:
054: // Was it compiled as deprecated?
055: if (getAttribute(idDeprecated) != null) {
056: this .modifiers |= M_DEPRECATED;
057: }
058:
059: // Was it synthesized by the compiler?
060: if (getAttribute(idSynthetic) != null) {
061: this .modifiers |= M_SYNTHETIC;
062: }
063: }
064:
065: /**
066: * Constructor for an inner class.
067: */
068: public BinaryMember(ClassDefinition innerClass) {
069: super (innerClass);
070: }
071:
072: /**
073: * Inline allowed (currently only allowed for the constructor of Object).
074: */
075: public boolean isInlineable(Environment env, boolean fromFinal) {
076: // It is possible for 'getSuperClass()' to return null due to error
077: // recovery from cyclic inheritace. Can this cause a problem here?
078: return isConstructor()
079: && (getClassDefinition().getSuperClass() == null);
080: }
081:
082: /**
083: * Get arguments
084: */
085: public Vector getArguments() {
086: if (isConstructor()
087: && (getClassDefinition().getSuperClass() == null)) {
088: Vector v = new Vector();
089: v.addElement(new LocalMember(0, getClassDefinition(), 0,
090: getClassDefinition().getType(), idThis));
091: return v;
092: }
093: return null;
094: }
095:
096: /**
097: * Get exceptions
098: */
099: public ClassDeclaration[] getExceptions(Environment env) {
100: if ((!isMethod()) || (exp != null)) {
101: return exp;
102: }
103: byte data[] = getAttribute(idExceptions);
104: if (data == null) {
105: return new ClassDeclaration[0];
106: }
107:
108: try {
109: BinaryConstantPool cpool = ((BinaryClass) getClassDefinition())
110: .getConstants();
111: DataInputStream in = new DataInputStream(
112: new ByteArrayInputStream(data));
113: // JVM 4.7.5 Exceptions_attribute.number_of_exceptions
114: int n = in.readUnsignedShort();
115: exp = new ClassDeclaration[n];
116: for (int i = 0; i < n; i++) {
117: // JVM 4.7.5 Exceptions_attribute.exception_index_table[]
118: exp[i] = cpool.getDeclaration(env, in
119: .readUnsignedShort());
120: }
121: return exp;
122: } catch (IOException e) {
123: throw new CompilerError(e);
124: }
125: }
126:
127: /**
128: * Get documentation
129: */
130: public String getDocumentation() {
131: if (documentation != null) {
132: return documentation;
133: }
134: byte data[] = getAttribute(idDocumentation);
135: if (data == null) {
136: return null;
137: }
138: try {
139: return documentation = new DataInputStream(
140: new ByteArrayInputStream(data)).readUTF();
141: } catch (IOException e) {
142: throw new CompilerError(e);
143: }
144: }
145:
146: /**
147: * Check if constant: Will it inline away to a constant?
148: * This override is needed to solve bug 4128266. It is also
149: * integral to the solution of 4119776.
150: */
151: private boolean isConstantCache = false;
152: private boolean isConstantCached = false;
153:
154: public boolean isConstant() {
155: if (!isConstantCached) {
156: isConstantCache = isFinal() && isVariable()
157: && getAttribute(idConstantValue) != null;
158: isConstantCached = true;
159: }
160: return isConstantCache;
161: }
162:
163: /**
164: * Get the value
165: */
166: public Node getValue(Environment env) {
167: if (isMethod()) {
168: return null;
169: }
170: if (!isFinal()) {
171: return null;
172: }
173: if (getValue() != null) {
174: return (Expression) getValue();
175: }
176: byte data[] = getAttribute(idConstantValue);
177: if (data == null) {
178: return null;
179: }
180:
181: try {
182: BinaryConstantPool cpool = ((BinaryClass) getClassDefinition())
183: .getConstants();
184: // JVM 4.7.3 ConstantValue.constantvalue_index
185: Object obj = cpool
186: .getValue(new DataInputStream(
187: new ByteArrayInputStream(data))
188: .readUnsignedShort());
189: switch (getType().getTypeCode()) {
190: case TC_BOOLEAN:
191: setValue(new BooleanExpression(0, ((Number) obj)
192: .intValue() != 0));
193: break;
194: case TC_BYTE:
195: case TC_SHORT:
196: case TC_CHAR:
197: case TC_INT:
198: setValue(new IntExpression(0, ((Number) obj).intValue()));
199: break;
200: case TC_LONG:
201: setValue(new LongExpression(0, ((Number) obj)
202: .longValue()));
203: break;
204: case TC_FLOAT:
205: setValue(new FloatExpression(0, ((Number) obj)
206: .floatValue()));
207: break;
208: case TC_DOUBLE:
209: setValue(new DoubleExpression(0, ((Number) obj)
210: .doubleValue()));
211: break;
212: case TC_CLASS:
213: setValue(new StringExpression(0, (String) cpool
214: .getValue(((Number) obj).intValue())));
215: break;
216: }
217: return (Expression) getValue();
218: } catch (IOException e) {
219: throw new CompilerError(e);
220: }
221: }
222:
223: /**
224: * Get a field attribute
225: */
226: public byte[] getAttribute(Identifier name) {
227: for (BinaryAttribute att = atts; att != null; att = att.next) {
228: if (att.name.equals(name)) {
229: return att.data;
230: }
231: }
232: return null;
233: }
234:
235: public boolean deleteAttribute(Identifier name) {
236: BinaryAttribute walker = null, next = null;
237:
238: boolean succeed = false;
239:
240: while (atts.name.equals(name)) {
241: atts = atts.next;
242: succeed = true;
243: }
244: for (walker = atts; walker != null; walker = next) {
245: next = walker.next;
246: if (next != null) {
247: if (next.name.equals(name)) {
248: walker.next = next.next;
249: next = next.next;
250: succeed = true;
251: }
252: }
253: }
254: for (walker = atts; walker != null; walker = walker.next) {
255: if (walker.name.equals(name)) {
256: throw new InternalError("Found attribute " + name);
257: }
258: }
259:
260: return succeed;
261: }
262:
263: /*
264: * Add an attribute to a field
265: */
266: public void addAttribute(Identifier name, byte data[],
267: Environment env) {
268: this .atts = new BinaryAttribute(name, data, this .atts);
269: // Make sure that the new attribute is in the constant pool
270: ((BinaryClass) (this.clazz)).cpool.indexString(name.toString(),
271: env);
272: }
273:
274: }
|