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.Map;
022: import java.util.LinkedList;
023: import java.util.ListIterator;
024:
025: // Note: if you define a new subclass of AttributeInfo, then
026: // update AttributeInfo.read(), .copy(), and (maybe) write().
027:
028: /**
029: * <code>attribute_info</code> structure.
030: */
031: public class AttributeInfo {
032: protected ConstPool constPool;
033: int name;
034: byte[] info;
035:
036: protected AttributeInfo(ConstPool cp, int attrname, byte[] attrinfo) {
037: constPool = cp;
038: name = attrname;
039: info = attrinfo;
040: }
041:
042: protected AttributeInfo(ConstPool cp, String attrname) {
043: this (cp, attrname, (byte[]) null);
044: }
045:
046: /**
047: * Constructs an <code>attribute_info</code> structure.
048: *
049: * @param cp constant pool table
050: * @param attrname attribute name
051: * @param attrinfo <code>info</code> field
052: * of <code>attribute_info</code> structure.
053: */
054: public AttributeInfo(ConstPool cp, String attrname, byte[] attrinfo) {
055: this (cp, cp.addUtf8Info(attrname), attrinfo);
056: }
057:
058: protected AttributeInfo(ConstPool cp, int n, DataInputStream in)
059: throws IOException {
060: constPool = cp;
061: name = n;
062: int len = in.readInt();
063: info = new byte[len];
064: if (len > 0)
065: in.readFully(info);
066: }
067:
068: static AttributeInfo read(ConstPool cp, DataInputStream in)
069: throws IOException {
070: int name = in.readUnsignedShort();
071: String nameStr = cp.getUtf8Info(name);
072: if (nameStr.charAt(0) < 'L') {
073: if (nameStr.equals(AnnotationDefaultAttribute.tag))
074: return new AnnotationDefaultAttribute(cp, name, in);
075: else if (nameStr.equals(CodeAttribute.tag))
076: return new CodeAttribute(cp, name, in);
077: else if (nameStr.equals(ConstantAttribute.tag))
078: return new ConstantAttribute(cp, name, in);
079: else if (nameStr.equals(DeprecatedAttribute.tag))
080: return new DeprecatedAttribute(cp, name, in);
081: else if (nameStr.equals(EnclosingMethodAttribute.tag))
082: return new EnclosingMethodAttribute(cp, name, in);
083: else if (nameStr.equals(ExceptionsAttribute.tag))
084: return new ExceptionsAttribute(cp, name, in);
085: else if (nameStr.equals(InnerClassesAttribute.tag))
086: return new InnerClassesAttribute(cp, name, in);
087: } else {
088: /* Note that the names of Annotations attributes begin with 'R'.
089: */
090: if (nameStr.equals(LineNumberAttribute.tag))
091: return new LineNumberAttribute(cp, name, in);
092: else if (nameStr.equals(LocalVariableAttribute.tag)
093: || nameStr.equals(LocalVariableAttribute.typeTag))
094: return new LocalVariableAttribute(cp, name, in);
095: else if (nameStr.equals(AnnotationsAttribute.visibleTag)
096: || nameStr
097: .equals(AnnotationsAttribute.invisibleTag)) {
098: // RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations
099: return new AnnotationsAttribute(cp, name, in);
100: } else if (nameStr
101: .equals(ParameterAnnotationsAttribute.visibleTag)
102: || nameStr
103: .equals(ParameterAnnotationsAttribute.invisibleTag))
104: return new ParameterAnnotationsAttribute(cp, name, in);
105: else if (nameStr.equals(SignatureAttribute.tag))
106: return new SignatureAttribute(cp, name, in);
107: else if (nameStr.equals(SourceFileAttribute.tag))
108: return new SourceFileAttribute(cp, name, in);
109: else if (nameStr.equals(SyntheticAttribute.tag))
110: return new SyntheticAttribute(cp, name, in);
111: else if (nameStr.equals(StackMapTable.tag))
112: return new StackMapTable(cp, name, in);
113: }
114:
115: return new AttributeInfo(cp, name, in);
116: }
117:
118: /**
119: * Returns an attribute name.
120: */
121: public String getName() {
122: return constPool.getUtf8Info(name);
123: }
124:
125: /**
126: * Returns a constant pool table.
127: */
128: public ConstPool getConstPool() {
129: return constPool;
130: }
131:
132: /**
133: * Returns the length of this <code>attribute_info</code>
134: * structure.
135: * The returned value is <code>attribute_length + 6</code>.
136: */
137: public int length() {
138: return info.length + 6;
139: }
140:
141: /**
142: * Returns the <code>info</code> field
143: * of this <code>attribute_info</code> structure.
144: *
145: * <p>This method is not available if the object is an instance
146: * of <code>CodeAttribute</code>.
147: */
148: public byte[] get() {
149: return info;
150: }
151:
152: /**
153: * Sets the <code>info</code> field
154: * of this <code>attribute_info</code> structure.
155: *
156: * <p>This method is not available if the object is an instance
157: * of <code>CodeAttribute</code>.
158: */
159: public void set(byte[] newinfo) {
160: info = newinfo;
161: }
162:
163: /**
164: * Makes a copy. Class names are replaced according to the
165: * given <code>Map</code> object.
166: *
167: * @param newCp the constant pool table used by the new copy.
168: * @param classnames pairs of replaced and substituted
169: * class names.
170: */
171: public AttributeInfo copy(ConstPool newCp, Map classnames) {
172: int s = info.length;
173: byte[] srcInfo = info;
174: byte[] newInfo = new byte[s];
175: for (int i = 0; i < s; ++i)
176: newInfo[i] = srcInfo[i];
177:
178: return new AttributeInfo(newCp, getName(), newInfo);
179: }
180:
181: void write(DataOutputStream out) throws IOException {
182: out.writeShort(name);
183: out.writeInt(info.length);
184: if (info.length > 0)
185: out.write(info);
186: }
187:
188: static int getLength(LinkedList list) {
189: int size = 0;
190: int n = list.size();
191: for (int i = 0; i < n; ++i) {
192: AttributeInfo attr = (AttributeInfo) list.get(i);
193: size += attr.length();
194: }
195:
196: return size;
197: }
198:
199: static AttributeInfo lookup(LinkedList list, String name) {
200: if (list == null)
201: return null;
202:
203: ListIterator iterator = list.listIterator();
204: while (iterator.hasNext()) {
205: AttributeInfo ai = (AttributeInfo) iterator.next();
206: if (ai.getName().equals(name))
207: return ai;
208: }
209:
210: return null; // no such attribute
211: }
212:
213: static synchronized void remove(LinkedList list, String name) {
214: if (list == null)
215: return;
216:
217: ListIterator iterator = list.listIterator();
218: while (iterator.hasNext()) {
219: AttributeInfo ai = (AttributeInfo) iterator.next();
220: if (ai.getName().equals(name))
221: iterator.remove();
222: }
223: }
224:
225: static void writeAll(LinkedList list, DataOutputStream out)
226: throws IOException {
227: if (list == null)
228: return;
229:
230: int n = list.size();
231: for (int i = 0; i < n; ++i) {
232: AttributeInfo attr = (AttributeInfo) list.get(i);
233: attr.write(out);
234: }
235: }
236:
237: static LinkedList copyAll(LinkedList list, ConstPool cp) {
238: if (list == null)
239: return null;
240:
241: LinkedList newList = new LinkedList();
242: int n = list.size();
243: for (int i = 0; i < n; ++i) {
244: AttributeInfo attr = (AttributeInfo) list.get(i);
245: newList.add(attr.copy(cp, null));
246: }
247:
248: return newList;
249: }
250: }
|