001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.bytecode;
017:
018: import java.io.DataInputStream;
019: import java.io.DataOutputStream;
020: import java.io.IOException;
021: import java.util.List;
022: import java.util.LinkedList;
023:
024: /**
025: * <code>field_info</code> structure.
026: *
027: * @see javassist.CtField#getFieldInfo()
028: */
029: public final class FieldInfo {
030: ConstPool constPool;
031: int accessFlags;
032: int name;
033: String cachedName;
034: String cachedType;
035: int descriptor;
036: LinkedList attribute; // may be null.
037:
038: private FieldInfo(ConstPool cp) {
039: constPool = cp;
040: accessFlags = 0;
041: attribute = null;
042: }
043:
044: /**
045: * Constructs a <code>field_info</code> structure.
046: *
047: * @param cp a constant pool table
048: * @param fieldName field name
049: * @param desc field descriptor
050: *
051: * @see Descriptor
052: */
053: public FieldInfo(ConstPool cp, String fieldName, String desc) {
054: this (cp);
055: name = cp.addUtf8Info(fieldName);
056: cachedName = fieldName;
057: descriptor = cp.addUtf8Info(desc);
058: }
059:
060: FieldInfo(ConstPool cp, DataInputStream in) throws IOException {
061: this (cp);
062: read(in);
063: }
064:
065: /**
066: * Returns a string representation of the object.
067: */
068: public String toString() {
069: return getName() + " " + getDescriptor();
070: }
071:
072: /**
073: * Copies all constant pool items to a given new constant pool
074: * and replaces the original items with the new ones.
075: * This is used for garbage collecting the items of removed fields
076: * and methods.
077: *
078: * @param cp the destination
079: */
080: void compact(ConstPool cp) {
081: name = cp.addUtf8Info(getName());
082: descriptor = cp.addUtf8Info(getDescriptor());
083: attribute = AttributeInfo.copyAll(attribute, cp);
084: constPool = cp;
085: }
086:
087: void prune(ConstPool cp) {
088: LinkedList newAttributes = new LinkedList();
089: AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag);
090: if (invisibleAnnotations != null) {
091: invisibleAnnotations = invisibleAnnotations.copy(cp, null);
092: newAttributes.add(invisibleAnnotations);
093: }
094:
095: AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag);
096: if (visibleAnnotations != null) {
097: visibleAnnotations = visibleAnnotations.copy(cp, null);
098: newAttributes.add(visibleAnnotations);
099: }
100:
101: int index = getConstantValue();
102: if (index != 0) {
103: index = constPool.copy(index, cp, null);
104: newAttributes.add(new ConstantAttribute(cp, index));
105: }
106:
107: attribute = newAttributes;
108: name = cp.addUtf8Info(getName());
109: descriptor = cp.addUtf8Info(getDescriptor());
110: constPool = cp;
111: }
112:
113: /**
114: * Returns the constant pool table used
115: * by this <code>field_info</code>.
116: */
117: public ConstPool getConstPool() {
118: return constPool;
119: }
120:
121: /**
122: * Returns the field name.
123: */
124: public String getName() {
125: if (cachedName == null)
126: cachedName = constPool.getUtf8Info(name);
127:
128: return cachedName;
129: }
130:
131: /**
132: * Sets the field name.
133: */
134: public void setName(String newName) {
135: name = constPool.addUtf8Info(newName);
136: cachedName = newName;
137: }
138:
139: /**
140: * Returns the access flags.
141: *
142: * @see AccessFlag
143: */
144: public int getAccessFlags() {
145: return accessFlags;
146: }
147:
148: /**
149: * Sets the access flags.
150: *
151: * @see AccessFlag
152: */
153: public void setAccessFlags(int acc) {
154: accessFlags = acc;
155: }
156:
157: /**
158: * Returns the field descriptor.
159: *
160: * @see Descriptor
161: */
162: public String getDescriptor() {
163: return constPool.getUtf8Info(descriptor);
164: }
165:
166: /**
167: * Sets the field descriptor.
168: *
169: * @see Descriptor
170: */
171: public void setDescriptor(String desc) {
172: if (!desc.equals(getDescriptor()))
173: descriptor = constPool.addUtf8Info(desc);
174: }
175:
176: /**
177: * Finds a ConstantValue attribute and returns the index into
178: * the <code>constant_pool</code> table.
179: *
180: * @return 0 if a ConstantValue attribute is not found.
181: */
182: public int getConstantValue() {
183: if ((accessFlags & AccessFlag.STATIC) == 0)
184: return 0;
185:
186: ConstantAttribute attr = (ConstantAttribute) getAttribute(ConstantAttribute.tag);
187: if (attr == null)
188: return 0;
189: else
190: return attr.getConstantValue();
191: }
192:
193: /**
194: * Returns all the attributes. The returned <code>List</code> object
195: * is shared with this object. If you add a new attribute to the list,
196: * the attribute is also added to the field represented by this
197: * object. If you remove an attribute from the list, it is also removed
198: * from the field.
199: *
200: * @return a list of <code>AttributeInfo</code> objects.
201: * @see AttributeInfo
202: */
203: public List getAttributes() {
204: if (attribute == null)
205: attribute = new LinkedList();
206:
207: return attribute;
208: }
209:
210: /**
211: * Returns the attribute with the specified name.
212: * It returns null if the specified attribute is not found.
213: *
214: * @param name attribute name
215: * @see #getAttributes()
216: */
217: public AttributeInfo getAttribute(String name) {
218: return AttributeInfo.lookup(attribute, name);
219: }
220:
221: /**
222: * Appends an attribute. If there is already an attribute with
223: * the same name, the new one substitutes for it.
224: *
225: * @see #getAttributes()
226: */
227: public void addAttribute(AttributeInfo info) {
228: if (attribute == null)
229: attribute = new LinkedList();
230:
231: AttributeInfo.remove(attribute, info.getName());
232: attribute.add(info);
233: }
234:
235: private void read(DataInputStream in) throws IOException {
236: accessFlags = in.readUnsignedShort();
237: name = in.readUnsignedShort();
238: descriptor = in.readUnsignedShort();
239: int n = in.readUnsignedShort();
240: attribute = new LinkedList();
241: for (int i = 0; i < n; ++i)
242: attribute.add(AttributeInfo.read(constPool, in));
243: }
244:
245: void write(DataOutputStream out) throws IOException {
246: out.writeShort(accessFlags);
247: out.writeShort(name);
248: out.writeShort(descriptor);
249: if (attribute == null)
250: out.writeShort(0);
251: else {
252: out.writeShort(attribute.size());
253: AttributeInfo.writeAll(attribute, out);
254: }
255: }
256: }
|