xref: /aosp_15_r20/external/javassist/src/main/javassist/bytecode/InnerClassesAttribute.java (revision f1fbf3c2ab775ce834e0af96b7a85bdc7a0eac65)
1*f1fbf3c2SXin Li /*
2*f1fbf3c2SXin Li  * Javassist, a Java-bytecode translator toolkit.
3*f1fbf3c2SXin Li  * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
4*f1fbf3c2SXin Li  *
5*f1fbf3c2SXin Li  * The contents of this file are subject to the Mozilla Public License Version
6*f1fbf3c2SXin Li  * 1.1 (the "License"); you may not use this file except in compliance with
7*f1fbf3c2SXin Li  * the License.  Alternatively, the contents of this file may be used under
8*f1fbf3c2SXin Li  * the terms of the GNU Lesser General Public License Version 2.1 or later,
9*f1fbf3c2SXin Li  * or the Apache License Version 2.0.
10*f1fbf3c2SXin Li  *
11*f1fbf3c2SXin Li  * Software distributed under the License is distributed on an "AS IS" basis,
12*f1fbf3c2SXin Li  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13*f1fbf3c2SXin Li  * for the specific language governing rights and limitations under the
14*f1fbf3c2SXin Li  * License.
15*f1fbf3c2SXin Li  */
16*f1fbf3c2SXin Li 
17*f1fbf3c2SXin Li package javassist.bytecode;
18*f1fbf3c2SXin Li 
19*f1fbf3c2SXin Li import java.io.DataInputStream;
20*f1fbf3c2SXin Li import java.io.IOException;
21*f1fbf3c2SXin Li import java.util.Map;
22*f1fbf3c2SXin Li 
23*f1fbf3c2SXin Li /**
24*f1fbf3c2SXin Li  * <code>InnerClasses_attribute</code>.
25*f1fbf3c2SXin Li  */
26*f1fbf3c2SXin Li public class InnerClassesAttribute extends AttributeInfo {
27*f1fbf3c2SXin Li     /**
28*f1fbf3c2SXin Li      * The name of this attribute <code>"InnerClasses"</code>.
29*f1fbf3c2SXin Li      */
30*f1fbf3c2SXin Li     public static final String tag = "InnerClasses";
31*f1fbf3c2SXin Li 
InnerClassesAttribute(ConstPool cp, int n, DataInputStream in)32*f1fbf3c2SXin Li     InnerClassesAttribute(ConstPool cp, int n, DataInputStream in)
33*f1fbf3c2SXin Li         throws IOException
34*f1fbf3c2SXin Li     {
35*f1fbf3c2SXin Li         super(cp, n, in);
36*f1fbf3c2SXin Li     }
37*f1fbf3c2SXin Li 
InnerClassesAttribute(ConstPool cp, byte[] info)38*f1fbf3c2SXin Li     private InnerClassesAttribute(ConstPool cp, byte[] info) {
39*f1fbf3c2SXin Li         super(cp, tag, info);
40*f1fbf3c2SXin Li     }
41*f1fbf3c2SXin Li 
42*f1fbf3c2SXin Li     /**
43*f1fbf3c2SXin Li      * Constructs an empty InnerClasses attribute.
44*f1fbf3c2SXin Li      *
45*f1fbf3c2SXin Li      * @see #append(String, String, String, int)
46*f1fbf3c2SXin Li      */
InnerClassesAttribute(ConstPool cp)47*f1fbf3c2SXin Li     public InnerClassesAttribute(ConstPool cp) {
48*f1fbf3c2SXin Li         super(cp, tag, new byte[2]);
49*f1fbf3c2SXin Li         ByteArray.write16bit(0, get(), 0);
50*f1fbf3c2SXin Li     }
51*f1fbf3c2SXin Li 
52*f1fbf3c2SXin Li     /**
53*f1fbf3c2SXin Li      * Returns <code>number_of_classes</code>.
54*f1fbf3c2SXin Li      */
tableLength()55*f1fbf3c2SXin Li     public int tableLength() { return ByteArray.readU16bit(get(), 0); }
56*f1fbf3c2SXin Li 
57*f1fbf3c2SXin Li     /**
58*f1fbf3c2SXin Li      * Returns <code>classes[nth].inner_class_info_index</code>.
59*f1fbf3c2SXin Li      */
innerClassIndex(int nth)60*f1fbf3c2SXin Li     public int innerClassIndex(int nth) {
61*f1fbf3c2SXin Li         return ByteArray.readU16bit(get(), nth * 8 + 2);
62*f1fbf3c2SXin Li     }
63*f1fbf3c2SXin Li 
64*f1fbf3c2SXin Li     /**
65*f1fbf3c2SXin Li      * Returns the class name indicated
66*f1fbf3c2SXin Li      * by <code>classes[nth].inner_class_info_index</code>.
67*f1fbf3c2SXin Li      * The class name is fully-qualified and separated by dot.
68*f1fbf3c2SXin Li      *
69*f1fbf3c2SXin Li      * @return null or the class name.
70*f1fbf3c2SXin Li      * @see ConstPool#getClassInfo(int)
71*f1fbf3c2SXin Li      */
innerClass(int nth)72*f1fbf3c2SXin Li     public String innerClass(int nth) {
73*f1fbf3c2SXin Li         int i = innerClassIndex(nth);
74*f1fbf3c2SXin Li         if (i == 0)
75*f1fbf3c2SXin Li             return null;
76*f1fbf3c2SXin Li         return constPool.getClassInfo(i);
77*f1fbf3c2SXin Li     }
78*f1fbf3c2SXin Li 
79*f1fbf3c2SXin Li     /**
80*f1fbf3c2SXin Li      * Sets <code>classes[nth].inner_class_info_index</code> to
81*f1fbf3c2SXin Li      * the given index.
82*f1fbf3c2SXin Li      */
setInnerClassIndex(int nth, int index)83*f1fbf3c2SXin Li     public void setInnerClassIndex(int nth, int index) {
84*f1fbf3c2SXin Li         ByteArray.write16bit(index, get(), nth * 8 + 2);
85*f1fbf3c2SXin Li     }
86*f1fbf3c2SXin Li 
87*f1fbf3c2SXin Li     /**
88*f1fbf3c2SXin Li      * Returns <code>classes[nth].outer_class_info_index</code>.
89*f1fbf3c2SXin Li      */
outerClassIndex(int nth)90*f1fbf3c2SXin Li     public int outerClassIndex(int nth) {
91*f1fbf3c2SXin Li         return ByteArray.readU16bit(get(), nth * 8 + 4);
92*f1fbf3c2SXin Li     }
93*f1fbf3c2SXin Li 
94*f1fbf3c2SXin Li     /**
95*f1fbf3c2SXin Li      * Returns the class name indicated
96*f1fbf3c2SXin Li      * by <code>classes[nth].outer_class_info_index</code>.
97*f1fbf3c2SXin Li      *
98*f1fbf3c2SXin Li      * @return null or the class name.
99*f1fbf3c2SXin Li      */
outerClass(int nth)100*f1fbf3c2SXin Li     public String outerClass(int nth) {
101*f1fbf3c2SXin Li         int i = outerClassIndex(nth);
102*f1fbf3c2SXin Li         if (i == 0)
103*f1fbf3c2SXin Li             return null;
104*f1fbf3c2SXin Li         return constPool.getClassInfo(i);
105*f1fbf3c2SXin Li     }
106*f1fbf3c2SXin Li 
107*f1fbf3c2SXin Li     /**
108*f1fbf3c2SXin Li      * Sets <code>classes[nth].outer_class_info_index</code> to
109*f1fbf3c2SXin Li      * the given index.
110*f1fbf3c2SXin Li      */
setOuterClassIndex(int nth, int index)111*f1fbf3c2SXin Li     public void setOuterClassIndex(int nth, int index) {
112*f1fbf3c2SXin Li         ByteArray.write16bit(index, get(), nth * 8 + 4);
113*f1fbf3c2SXin Li     }
114*f1fbf3c2SXin Li 
115*f1fbf3c2SXin Li     /**
116*f1fbf3c2SXin Li      * Returns <code>classes[nth].inner_name_index</code>.
117*f1fbf3c2SXin Li      */
innerNameIndex(int nth)118*f1fbf3c2SXin Li     public int innerNameIndex(int nth) {
119*f1fbf3c2SXin Li         return ByteArray.readU16bit(get(), nth * 8 + 6);
120*f1fbf3c2SXin Li     }
121*f1fbf3c2SXin Li 
122*f1fbf3c2SXin Li     /**
123*f1fbf3c2SXin Li      * Returns the simple class name indicated
124*f1fbf3c2SXin Li      * by <code>classes[nth].inner_name_index</code>.
125*f1fbf3c2SXin Li      *
126*f1fbf3c2SXin Li      * @return null or the class name.
127*f1fbf3c2SXin Li      */
innerName(int nth)128*f1fbf3c2SXin Li     public String innerName(int nth) {
129*f1fbf3c2SXin Li         int i = innerNameIndex(nth);
130*f1fbf3c2SXin Li         if (i == 0)
131*f1fbf3c2SXin Li             return null;
132*f1fbf3c2SXin Li         return constPool.getUtf8Info(i);
133*f1fbf3c2SXin Li     }
134*f1fbf3c2SXin Li 
135*f1fbf3c2SXin Li     /**
136*f1fbf3c2SXin Li      * Sets <code>classes[nth].inner_name_index</code> to
137*f1fbf3c2SXin Li      * the given index.
138*f1fbf3c2SXin Li      */
setInnerNameIndex(int nth, int index)139*f1fbf3c2SXin Li     public void setInnerNameIndex(int nth, int index) {
140*f1fbf3c2SXin Li         ByteArray.write16bit(index, get(), nth * 8 + 6);
141*f1fbf3c2SXin Li     }
142*f1fbf3c2SXin Li 
143*f1fbf3c2SXin Li     /**
144*f1fbf3c2SXin Li      * Returns <code>classes[nth].inner_class_access_flags</code>.
145*f1fbf3c2SXin Li      */
accessFlags(int nth)146*f1fbf3c2SXin Li     public int accessFlags(int nth) {
147*f1fbf3c2SXin Li         return ByteArray.readU16bit(get(), nth * 8 + 8);
148*f1fbf3c2SXin Li     }
149*f1fbf3c2SXin Li 
150*f1fbf3c2SXin Li     /**
151*f1fbf3c2SXin Li      * Sets <code>classes[nth].inner_class_access_flags</code> to
152*f1fbf3c2SXin Li      * the given index.
153*f1fbf3c2SXin Li      */
setAccessFlags(int nth, int flags)154*f1fbf3c2SXin Li     public void setAccessFlags(int nth, int flags) {
155*f1fbf3c2SXin Li         ByteArray.write16bit(flags, get(), nth * 8 + 8);
156*f1fbf3c2SXin Li     }
157*f1fbf3c2SXin Li 
158*f1fbf3c2SXin Li     /**
159*f1fbf3c2SXin Li      * Finds the entry for the given inner class.
160*f1fbf3c2SXin Li      *
161*f1fbf3c2SXin Li      * @param name      the fully-qualified class name separated by dot and $.
162*f1fbf3c2SXin Li      * @return the index or -1 if not found.
163*f1fbf3c2SXin Li      * @since 3.22
164*f1fbf3c2SXin Li      */
find(String name)165*f1fbf3c2SXin Li     public int find(String name) {
166*f1fbf3c2SXin Li         int n = tableLength();
167*f1fbf3c2SXin Li         for (int i = 0; i < n; i++)
168*f1fbf3c2SXin Li             if (name.equals(innerClass(i)))
169*f1fbf3c2SXin Li                 return i;
170*f1fbf3c2SXin Li 
171*f1fbf3c2SXin Li         return -1;
172*f1fbf3c2SXin Li     }
173*f1fbf3c2SXin Li 
174*f1fbf3c2SXin Li     /**
175*f1fbf3c2SXin Li      * Appends a new entry.
176*f1fbf3c2SXin Li      *
177*f1fbf3c2SXin Li      * @param inner     <code>inner_class_info_index</code>
178*f1fbf3c2SXin Li      * @param outer     <code>outer_class_info_index</code>
179*f1fbf3c2SXin Li      * @param name      <code>inner_name_index</code>
180*f1fbf3c2SXin Li      * @param flags     <code>inner_class_access_flags</code>
181*f1fbf3c2SXin Li      */
append(String inner, String outer, String name, int flags)182*f1fbf3c2SXin Li     public void append(String inner, String outer, String name, int flags) {
183*f1fbf3c2SXin Li         int i = constPool.addClassInfo(inner);
184*f1fbf3c2SXin Li         int o = constPool.addClassInfo(outer);
185*f1fbf3c2SXin Li         int n = constPool.addUtf8Info(name);
186*f1fbf3c2SXin Li         append(i, o, n, flags);
187*f1fbf3c2SXin Li     }
188*f1fbf3c2SXin Li 
189*f1fbf3c2SXin Li     /**
190*f1fbf3c2SXin Li      * Appends a new entry.
191*f1fbf3c2SXin Li      *
192*f1fbf3c2SXin Li      * @param inner     <code>inner_class_info_index</code>
193*f1fbf3c2SXin Li      * @param outer     <code>outer_class_info_index</code>
194*f1fbf3c2SXin Li      * @param name      <code>inner_name_index</code>
195*f1fbf3c2SXin Li      * @param flags     <code>inner_class_access_flags</code>
196*f1fbf3c2SXin Li      */
append(int inner, int outer, int name, int flags)197*f1fbf3c2SXin Li     public void append(int inner, int outer, int name, int flags) {
198*f1fbf3c2SXin Li         byte[] data = get();
199*f1fbf3c2SXin Li         int len = data.length;
200*f1fbf3c2SXin Li         byte[] newData = new byte[len + 8];
201*f1fbf3c2SXin Li         for (int i = 2; i < len; ++i)
202*f1fbf3c2SXin Li             newData[i] = data[i];
203*f1fbf3c2SXin Li 
204*f1fbf3c2SXin Li         int n = ByteArray.readU16bit(data, 0);
205*f1fbf3c2SXin Li         ByteArray.write16bit(n + 1, newData, 0);
206*f1fbf3c2SXin Li 
207*f1fbf3c2SXin Li         ByteArray.write16bit(inner, newData, len);
208*f1fbf3c2SXin Li         ByteArray.write16bit(outer, newData, len + 2);
209*f1fbf3c2SXin Li         ByteArray.write16bit(name, newData, len + 4);
210*f1fbf3c2SXin Li         ByteArray.write16bit(flags, newData, len + 6);
211*f1fbf3c2SXin Li 
212*f1fbf3c2SXin Li         set(newData);
213*f1fbf3c2SXin Li     }
214*f1fbf3c2SXin Li 
215*f1fbf3c2SXin Li     /**
216*f1fbf3c2SXin Li      * Removes the {@code nth} entry.  It does not eliminate
217*f1fbf3c2SXin Li      * constant pool items that the removed entry refers to.
218*f1fbf3c2SXin Li      * {@link ClassFile#compact()} should be executed to remove
219*f1fbf3c2SXin Li      * these unnecessary items.
220*f1fbf3c2SXin Li      *
221*f1fbf3c2SXin Li      * @param nth       0, 1, 2, ...
222*f1fbf3c2SXin Li      * @return  the number of items after the removal.
223*f1fbf3c2SXin Li      * @see ClassFile#compact()
224*f1fbf3c2SXin Li      */
remove(int nth)225*f1fbf3c2SXin Li     public int remove(int nth) {
226*f1fbf3c2SXin Li         byte[] data = get();
227*f1fbf3c2SXin Li         int len = data.length;
228*f1fbf3c2SXin Li         if (len < 10)
229*f1fbf3c2SXin Li             return 0;
230*f1fbf3c2SXin Li 
231*f1fbf3c2SXin Li         int n = ByteArray.readU16bit(data, 0);
232*f1fbf3c2SXin Li         int nthPos = 2 + nth * 8;
233*f1fbf3c2SXin Li         if (n <= nth)
234*f1fbf3c2SXin Li             return n;
235*f1fbf3c2SXin Li 
236*f1fbf3c2SXin Li         byte[] newData = new byte[len - 8];
237*f1fbf3c2SXin Li         ByteArray.write16bit(n - 1, newData, 0);
238*f1fbf3c2SXin Li         int i = 2, j = 2;
239*f1fbf3c2SXin Li         while (i < len)
240*f1fbf3c2SXin Li             if (i == nthPos)
241*f1fbf3c2SXin Li                 i += 8;
242*f1fbf3c2SXin Li             else
243*f1fbf3c2SXin Li                 newData[j++] = data[i++];
244*f1fbf3c2SXin Li 
245*f1fbf3c2SXin Li         set(newData);
246*f1fbf3c2SXin Li         return n - 1;
247*f1fbf3c2SXin Li     }
248*f1fbf3c2SXin Li 
249*f1fbf3c2SXin Li     /**
250*f1fbf3c2SXin Li      * Makes a copy.  Class names are replaced according to the
251*f1fbf3c2SXin Li      * given <code>Map</code> object.
252*f1fbf3c2SXin Li      *
253*f1fbf3c2SXin Li      * @param newCp     the constant pool table used by the new copy.
254*f1fbf3c2SXin Li      * @param classnames        pairs of replaced and substituted
255*f1fbf3c2SXin Li      *                          class names.
256*f1fbf3c2SXin Li      */
257*f1fbf3c2SXin Li     @Override
copy(ConstPool newCp, Map<String,String> classnames)258*f1fbf3c2SXin Li     public AttributeInfo copy(ConstPool newCp, Map<String,String> classnames) {
259*f1fbf3c2SXin Li         byte[] src = get();
260*f1fbf3c2SXin Li         byte[] dest = new byte[src.length];
261*f1fbf3c2SXin Li         ConstPool cp = getConstPool();
262*f1fbf3c2SXin Li         InnerClassesAttribute attr = new InnerClassesAttribute(newCp, dest);
263*f1fbf3c2SXin Li         int n = ByteArray.readU16bit(src, 0);
264*f1fbf3c2SXin Li         ByteArray.write16bit(n, dest, 0);
265*f1fbf3c2SXin Li         int j = 2;
266*f1fbf3c2SXin Li         for (int i = 0; i < n; ++i) {
267*f1fbf3c2SXin Li             int innerClass = ByteArray.readU16bit(src, j);
268*f1fbf3c2SXin Li             int outerClass = ByteArray.readU16bit(src, j + 2);
269*f1fbf3c2SXin Li             int innerName = ByteArray.readU16bit(src, j + 4);
270*f1fbf3c2SXin Li             int innerAccess = ByteArray.readU16bit(src, j + 6);
271*f1fbf3c2SXin Li 
272*f1fbf3c2SXin Li             if (innerClass != 0)
273*f1fbf3c2SXin Li                 innerClass = cp.copy(innerClass, newCp, classnames);
274*f1fbf3c2SXin Li 
275*f1fbf3c2SXin Li             ByteArray.write16bit(innerClass, dest, j);
276*f1fbf3c2SXin Li 
277*f1fbf3c2SXin Li             if (outerClass != 0)
278*f1fbf3c2SXin Li                 outerClass = cp.copy(outerClass, newCp, classnames);
279*f1fbf3c2SXin Li 
280*f1fbf3c2SXin Li             ByteArray.write16bit(outerClass, dest, j + 2);
281*f1fbf3c2SXin Li 
282*f1fbf3c2SXin Li             if (innerName != 0)
283*f1fbf3c2SXin Li                 innerName = cp.copy(innerName, newCp, classnames);
284*f1fbf3c2SXin Li 
285*f1fbf3c2SXin Li             ByteArray.write16bit(innerName, dest, j + 4);
286*f1fbf3c2SXin Li             ByteArray.write16bit(innerAccess, dest, j + 6);
287*f1fbf3c2SXin Li             j += 8;
288*f1fbf3c2SXin Li         }
289*f1fbf3c2SXin Li 
290*f1fbf3c2SXin Li         return attr;
291*f1fbf3c2SXin Li     }
292*f1fbf3c2SXin Li }
293