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.util.Map;
020: import java.io.IOException;
021:
022: /**
023: * <code>InnerClasses_attribute</code>.
024: */
025: public class InnerClassesAttribute extends AttributeInfo {
026: /**
027: * The name of this attribute <code>"InnerClasses"</code>.
028: */
029: public static final String tag = "InnerClasses";
030:
031: InnerClassesAttribute(ConstPool cp, int n, DataInputStream in)
032: throws IOException {
033: super (cp, n, in);
034: }
035:
036: private InnerClassesAttribute(ConstPool cp, byte[] info) {
037: super (cp, tag, info);
038: }
039:
040: /**
041: * Constructs an empty InnerClasses attribute.
042: *
043: * @see #append(String, String, String, int)
044: */
045: public InnerClassesAttribute(ConstPool cp) {
046: super (cp, tag, new byte[2]);
047: ByteArray.write16bit(0, get(), 0);
048: }
049:
050: /**
051: * Returns <code>number_of_classes</code>.
052: */
053: public int tableLength() {
054: return ByteArray.readU16bit(get(), 0);
055: }
056:
057: /**
058: * Returns <code>classes[nth].inner_class_info_index</code>.
059: */
060: public int innerClassIndex(int nth) {
061: return ByteArray.readU16bit(get(), nth * 8 + 2);
062: }
063:
064: /**
065: * Returns the class name indicated
066: * by <code>classes[nth].inner_class_info_index</code>.
067: *
068: * @return null or the class name.
069: */
070: public String innerClass(int nth) {
071: int i = innerClassIndex(nth);
072: if (i == 0)
073: return null;
074: else
075: return constPool.getClassInfo(i);
076: }
077:
078: /**
079: * Sets <code>classes[nth].inner_class_info_index</code> to
080: * the given index.
081: */
082: public void setInnerClassIndex(int nth, int index) {
083: ByteArray.write16bit(index, get(), nth * 8 + 2);
084: }
085:
086: /**
087: * Returns <code>classes[nth].outer_class_info_index</code>.
088: */
089: public int outerClassIndex(int nth) {
090: return ByteArray.readU16bit(get(), nth * 8 + 4);
091: }
092:
093: /**
094: * Returns the class name indicated
095: * by <code>classes[nth].outer_class_info_index</code>.
096: *
097: * @return null or the class name.
098: */
099: public String outerClass(int nth) {
100: int i = outerClassIndex(nth);
101: if (i == 0)
102: return null;
103: else
104: return constPool.getClassInfo(i);
105: }
106:
107: /**
108: * Sets <code>classes[nth].outer_class_info_index</code> to
109: * the given index.
110: */
111: public void setOuterClassIndex(int nth, int index) {
112: ByteArray.write16bit(index, get(), nth * 8 + 4);
113: }
114:
115: /**
116: * Returns <code>classes[nth].inner_name_index</code>.
117: */
118: public int innerNameIndex(int nth) {
119: return ByteArray.readU16bit(get(), nth * 8 + 6);
120: }
121:
122: /**
123: * Returns the simple class name indicated
124: * by <code>classes[nth].inner_name_index</code>.
125: *
126: * @return null or the class name.
127: */
128: public String innerName(int nth) {
129: int i = innerNameIndex(nth);
130: if (i == 0)
131: return null;
132: else
133: return constPool.getUtf8Info(i);
134: }
135:
136: /**
137: * Sets <code>classes[nth].inner_name_index</code> to
138: * the given index.
139: */
140: public void setInnerNameIndex(int nth, int index) {
141: ByteArray.write16bit(index, get(), nth * 8 + 6);
142: }
143:
144: /**
145: * Returns <code>classes[nth].inner_class_access_flags</code>.
146: */
147: public int accessFlags(int nth) {
148: return ByteArray.readU16bit(get(), nth * 8 + 8);
149: }
150:
151: /**
152: * Sets <code>classes[nth].inner_class_access_flags</code> to
153: * the given index.
154: */
155: public void setAccessFlags(int nth, int flags) {
156: ByteArray.write16bit(flags, get(), nth * 8 + 8);
157: }
158:
159: /**
160: * Appends a new entry.
161: *
162: * @param inner <code>inner_class_info_index</code>
163: * @param outer <code>outer_class_info_index</code>
164: * @param name <code>inner_name_index</code>
165: * @param flags <code>inner_class_access_flags</code>
166: */
167: public void append(String inner, String outer, String name,
168: int flags) {
169: int i = constPool.addClassInfo(inner);
170: int o = constPool.addClassInfo(outer);
171: int n = constPool.addUtf8Info(name);
172: append(i, o, n, flags);
173: }
174:
175: /**
176: * Appends a new entry.
177: *
178: * @param inner <code>inner_class_info_index</code>
179: * @param outer <code>outer_class_info_index</code>
180: * @param name <code>inner_name_index</code>
181: * @param flags <code>inner_class_access_flags</code>
182: */
183: public void append(int inner, int outer, int name, int flags) {
184: byte[] data = get();
185: int len = data.length;
186: byte[] newData = new byte[len + 8];
187: for (int i = 2; i < len; ++i)
188: newData[i] = data[i];
189:
190: int n = ByteArray.readU16bit(data, 0);
191: ByteArray.write16bit(n + 1, newData, 0);
192:
193: ByteArray.write16bit(inner, newData, len);
194: ByteArray.write16bit(outer, newData, len + 2);
195: ByteArray.write16bit(name, newData, len + 4);
196: ByteArray.write16bit(flags, newData, len + 6);
197:
198: set(newData);
199: }
200:
201: /**
202: * Makes a copy. Class names are replaced according to the
203: * given <code>Map</code> object.
204: *
205: * @param newCp the constant pool table used by the new copy.
206: * @param classnames pairs of replaced and substituted
207: * class names.
208: */
209: public AttributeInfo copy(ConstPool newCp, Map classnames) {
210: byte[] src = get();
211: byte[] dest = new byte[src.length];
212: ConstPool cp = getConstPool();
213: InnerClassesAttribute attr = new InnerClassesAttribute(newCp,
214: dest);
215: int n = ByteArray.readU16bit(src, 0);
216: ByteArray.write16bit(n, dest, 0);
217: int j = 2;
218: for (int i = 0; i < n; ++i) {
219: int innerClass = ByteArray.readU16bit(src, j);
220: int outerClass = ByteArray.readU16bit(src, j + 2);
221: int innerName = ByteArray.readU16bit(src, j + 4);
222: int innerAccess = ByteArray.readU16bit(src, j + 6);
223:
224: if (innerClass != 0)
225: innerClass = cp.copy(innerClass, newCp, classnames);
226:
227: ByteArray.write16bit(innerClass, dest, j);
228:
229: if (outerClass != 0)
230: outerClass = cp.copy(outerClass, newCp, classnames);
231:
232: ByteArray.write16bit(outerClass, dest, j + 2);
233:
234: if (innerName != 0)
235: innerName = cp.copy(innerName, newCp, classnames);
236:
237: ByteArray.write16bit(innerName, dest, j + 4);
238: ByteArray.write16bit(innerAccess, dest, j + 6);
239: j += 8;
240: }
241:
242: return attr;
243: }
244: }
|