001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package EDU.purdue.cs.bloat.reflect;
022:
023: /**
024: * A Constant is used to represent an item in the constant pool of a class.
025: *
026: * @author Nate Nystrom (<a
027: * href="mailto:nystrom@cs.purdue.edu">nystrom@cs.purdue.edu</a>)
028: */
029: public final class Constant {
030: private int tag;
031:
032: private Object value;
033:
034: /**
035: * Constant tag for class types. This is used to reference other classes,
036: * such as the superclass, and is used by the checkcast and instanceof
037: * instructions. The Fieldref, Methodref and InterfaceMethodref constant
038: * types refer to this constant type.
039: */
040: public static final byte CLASS = 7;
041:
042: /**
043: * Constant tag for field references. This is used to reference a field in
044: * (possibly) another class. The getfield, putfield, getstatic, and
045: * putstatic instructions use this constant type.
046: */
047: public static final byte FIELD_REF = 9;
048:
049: /**
050: * Constant tag for method references. This is used to reference a method in
051: * (possibly) another class. The invokevirtual, invokespecial, and
052: * invokestatic instructions use this constant type.
053: */
054: public static final byte METHOD_REF = 10;
055:
056: /**
057: * Constant tag for java.lang.String constants. The actual string value is
058: * stored indirectly in a Utf8 constant.
059: */
060: public static final byte STRING = 8;
061:
062: /**
063: * Constant tag for int, short, byte, char, and boolean constants.
064: */
065: public static final byte INTEGER = 3;
066:
067: /**
068: * Constant tag for float constants.
069: */
070: public static final byte FLOAT = 4;
071:
072: /**
073: * Constant tag for long constants.
074: */
075: public static final byte LONG = 5;
076:
077: /**
078: * Constant tag for double constants.
079: */
080: public static final byte DOUBLE = 6;
081:
082: /**
083: * Constant tag for method references. This is used to reference a method in
084: * an interface. The invokeinterface instruction uses this constant type.
085: */
086: public static final byte INTERFACE_METHOD_REF = 11;
087:
088: /**
089: * Constant tag for holding the name and type of a field or method. The
090: * Fieldref, Methodref and InterfaceMethodref constant types refer to this
091: * constant type.
092: */
093: public static final byte NAME_AND_TYPE = 12;
094:
095: /**
096: * Constant tag for holding the a UTF8 format string. The string is used to
097: * hold the name and type descriptor for NameandType constants, the class
098: * name for Class constants, the string value for String constants.
099: */
100: public static final byte UTF8 = 1;
101:
102: /**
103: * @param tag
104: * The constant's tag.
105: * @param value
106: * The constant's value.
107: */
108: public Constant(final int tag, final Object value) {
109: this .tag = tag;
110: this .value = value;
111: }
112:
113: /**
114: * Get the tag of the constant.
115: *
116: * @return The tag.
117: */
118: public final int tag() {
119: return tag;
120: }
121:
122: /**
123: * Get the value of the constant.
124: *
125: * @return The value.
126: */
127: public final Object value() {
128: return value;
129: }
130:
131: /**
132: * Hash the constant.
133: *
134: * @return The hash code.
135: */
136: public int hashCode() {
137: switch (tag) {
138: case CLASS:
139: case STRING:
140: case INTEGER:
141: case FLOAT:
142: case LONG:
143: case DOUBLE:
144: case UTF8:
145: return tag ^ value.hashCode();
146: case FIELD_REF:
147: case METHOD_REF:
148: case INTERFACE_METHOD_REF:
149: case NAME_AND_TYPE:
150: return tag ^ ((int[]) value)[0] ^ ((int[]) value)[1];
151: }
152:
153: return tag;
154: }
155:
156: /**
157: * Check if an object is equal to this constant.
158: *
159: * @param other
160: * The object to compare against.
161: * @return true if equal, false if not.
162: */
163: public boolean equals(final Object other) {
164: if (!(other instanceof Constant)) {
165: return false;
166: }
167:
168: final Constant c = (Constant) other;
169:
170: if (tag != c.tag) {
171: return false;
172: }
173:
174: switch (tag) {
175: case CLASS:
176: case STRING:
177: case INTEGER:
178: case FLOAT:
179: case LONG:
180: case DOUBLE:
181: case UTF8:
182: return value.equals(c.value);
183: case FIELD_REF:
184: case METHOD_REF:
185: case INTERFACE_METHOD_REF:
186: case NAME_AND_TYPE:
187: return (((int[]) value)[0] == ((int[]) c.value)[0])
188: && (((int[]) value)[1] == ((int[]) c.value)[1]);
189: }
190:
191: return false;
192: }
193:
194: /**
195: * Convert the constant to a string.
196: *
197: * @return A string representation of the constant.
198: */
199: public String toString() {
200: switch (tag) {
201: case CLASS:
202: return "Class " + value.toString();
203: case STRING:
204: return "String " + value.toString();
205: case INTEGER:
206: return "Integer " + value.toString();
207: case FLOAT:
208: return "Float " + value.toString();
209: case LONG:
210: return "Long " + value.toString();
211: case DOUBLE:
212: return "Double " + value.toString();
213: case UTF8:
214: final StringBuffer sb = new StringBuffer();
215: final String s = (String) value;
216: for (int i = 0; i < s.length(); i++) {
217: final char c = s.charAt(i);
218: if (Character.isWhitespace(c)
219: || ((0x20 <= c) && (c <= 0x7e))) {
220: sb.append(c);
221: } else {
222: sb.append("\\u");
223: sb.append(Integer.toHexString(c));
224: }
225: if (sb.length() > 50) {
226: sb.append("...");
227: break;
228: }
229: }
230: return "Utf8 '" + sb.toString() + "'";
231: case FIELD_REF:
232: return "Fieldref " + ((int[]) value)[0] + " "
233: + ((int[]) value)[1];
234: case METHOD_REF:
235: return "Methodref " + ((int[]) value)[0] + " "
236: + ((int[]) value)[1];
237: case INTERFACE_METHOD_REF:
238: return "InterfaceMethodref " + ((int[]) value)[0] + " "
239: + ((int[]) value)[1];
240: case NAME_AND_TYPE:
241: return "NameandType " + ((int[]) value)[0] + " "
242: + ((int[]) value)[1];
243: }
244:
245: return "unknown constant";
246: }
247: }
|