1   // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import java.io.IOException;
6   import java.util.ArrayList;
7   
8   import static jminusminus.CLConstants.*;
9   
10  /**
11   * This class provides a representation of the ClassFile structure.
12   */
13  class CLFile {
14      /**
15       * ClassFile.magic item.
16       */
17      public long magic; // 0xCAFEBABE
18  
19      /**
20       * ClassFile.minor_version item.
21       */
22      public int minorVersion;
23  
24      /**
25       * ClassFile.major_version item.
26       */
27      public int majorVersion;
28  
29      /**
30       * ClassFile.constant_pool_count item.
31       */
32      public int constantPoolCount;
33  
34      /**
35       * ClassFile.constant_pool item.
36       */
37      public CLConstantPool constantPool;
38  
39      /**
40       * ClassFile.access_flags item.
41       */
42      public int accessFlags;
43  
44      /**
45       * ClassFile.this_class item.
46       */
47      public int thisClass;
48  
49      /**
50       * ClassFile.super_class item.
51       */
52      public int superClass;
53  
54      /**
55       * ClassFile.interfaces_count item.
56       */
57      public int interfacesCount;
58  
59      /**
60       * ClassFile.interfaces item.
61       */
62      public ArrayList<Integer> interfaces;
63  
64      /**
65       * ClassFile.fields_count item.
66       */
67      public int fieldsCount;
68  
69      /**
70       * ClassFile.fields item.
71       */
72      public ArrayList<CLFieldInfo> fields;
73  
74      /**
75       * ClassFile.methods_count item.
76       */
77      public int methodsCount;
78  
79      /**
80       * ClassFile.methods item.
81       */
82      public ArrayList<CLMethodInfo> methods;
83  
84      /**
85       * ClassFile.attributes_count item.
86       */
87      public int attributesCount;
88  
89      /**
90       * ClassFile.attributes item.
91       */
92      public ArrayList<CLAttributeInfo> attributes;
93  
94      /**
95       * Writes the contents of this class to the specified output stream.
96       *
97       * @param out output stream.
98       * @throws IOException if an error occurs while writing.
99       */
100     public void write(CLOutputStream out) throws IOException {
101         out.writeInt(magic);
102         out.writeShort(minorVersion);
103         out.writeShort(majorVersion);
104         out.writeShort(constantPoolCount);
105         constantPool.write(out);
106         out.writeShort(accessFlags);
107         out.writeShort(thisClass);
108         out.writeShort(superClass);
109         out.writeShort(interfacesCount);
110         for (Integer index : interfaces) {
111             out.writeShort(index.intValue());
112         }
113         out.writeShort(fieldsCount);
114         for (CLMemberInfo fieldInfo : fields) {
115             if (fieldInfo != null) {
116                 fieldInfo.write(out);
117             }
118         }
119         out.writeShort(methodsCount);
120         for (CLMemberInfo methodInfo : methods) {
121             if (methodInfo != null) {
122                 methodInfo.write(out);
123             }
124         }
125         out.writeShort(attributesCount);
126         for (CLAttributeInfo attributeInfo : attributes) {
127             if (attributeInfo != null) {
128                 attributeInfo.write(out);
129             }
130         }
131     }
132 
133     /**
134      * Returns a string identifying the inner class access permissions and properties contained in
135      * the specified mask of flags.
136      *
137      * @param accessFlags mask of access flags.
138      * @return a string identifying the inner class access permissions and properties.
139      */
140     public static String innerClassAccessFlagsToString(int accessFlags) {
141         StringBuffer b = new StringBuffer();
142         if ((accessFlags & ACC_PUBLIC) != 0) {
143             b.append("public ");
144         }
145         if ((accessFlags & ACC_PRIVATE) != 0) {
146             b.append("private ");
147         }
148         if ((accessFlags & ACC_PROTECTED) != 0) {
149             b.append("protected ");
150         }
151         if ((accessFlags & ACC_STATIC) != 0) {
152             b.append("static ");
153         }
154         if ((accessFlags & ACC_FINAL) != 0) {
155             b.append("final ");
156         }
157         if ((accessFlags & ACC_INTERFACE) != 0) {
158             b.append("interface ");
159         }
160         if ((accessFlags & ACC_ABSTRACT) != 0) {
161             b.append("abstract ");
162         }
163         if ((accessFlags & ACC_SYNTHETIC) != 0) {
164             b.append("synthetic ");
165         }
166         if ((accessFlags & ACC_ANNOTATION) != 0) {
167             b.append("annotation ");
168         }
169         if ((accessFlags & ACC_ENUM) != 0) {
170             b.append("enum ");
171         }
172         return b.toString().trim();
173     }
174 
175     /**
176      * Returns a string identifying the field access permissions and properties contained in the
177      * specified mask of flags.
178      *
179      * @param accessFlags mask of access flags.
180      * @return a string identifying the field access permissions and properties.
181      */
182     public static String fieldAccessFlagsToString(int accessFlags) {
183         StringBuffer b = new StringBuffer();
184         if ((accessFlags & ACC_PUBLIC) != 0) {
185             b.append("public ");
186         }
187         if ((accessFlags & ACC_PRIVATE) != 0) {
188             b.append("private ");
189         }
190         if ((accessFlags & ACC_PROTECTED) != 0) {
191             b.append("protected ");
192         }
193         if ((accessFlags & ACC_STATIC) != 0) {
194             b.append("static ");
195         }
196         if ((accessFlags & ACC_FINAL) != 0) {
197             b.append("final ");
198         }
199         if ((accessFlags & ACC_VOLATILE) != 0) {
200             b.append("volatile ");
201         }
202         if ((accessFlags & ACC_TRANSIENT) != 0) {
203             b.append("transient ");
204         }
205         if ((accessFlags & ACC_NATIVE) != 0) {
206             b.append("native ");
207         }
208         if ((accessFlags & ACC_SYNTHETIC) != 0) {
209             b.append("synthetic ");
210         }
211         if ((accessFlags & ACC_ENUM) != 0) {
212             b.append("enum ");
213         }
214         return b.toString().trim();
215     }
216 
217     /**
218      * Returns a string identifying the method access permissions and properties contained in the
219      * specified mask of flags.
220      *
221      * @param accessFlags mask of access flags.
222      * @return a string identifying the method access permissions and properties.
223      */
224     public static String methodAccessFlagsToString(int accessFlags) {
225         StringBuffer b = new StringBuffer();
226         if ((accessFlags & ACC_PUBLIC) != 0) {
227             b.append("public ");
228         }
229         if ((accessFlags & ACC_PRIVATE) != 0) {
230             b.append("private ");
231         }
232         if ((accessFlags & ACC_PROTECTED) != 0) {
233             b.append("protected ");
234         }
235         if ((accessFlags & ACC_STATIC) != 0) {
236             b.append("static ");
237         }
238         if ((accessFlags & ACC_FINAL) != 0) {
239             b.append("final ");
240         }
241         if ((accessFlags & ACC_SYNCHRONIZED) != 0) {
242             b.append("synchronized ");
243         }
244         if ((accessFlags & ACC_BRIDGE) != 0) {
245             b.append("bridge ");
246         }
247         if ((accessFlags & ACC_VARARGS) != 0) {
248             b.append("varargs ");
249         }
250         if ((accessFlags & ACC_NATIVE) != 0) {
251             b.append("native ");
252         }
253         if ((accessFlags & ACC_ABSTRACT) != 0) {
254             b.append("abstract ");
255         }
256         if ((accessFlags & ACC_STRICT) != 0) {
257             b.append("strict ");
258         }
259         if ((accessFlags & ACC_SYNTHETIC) != 0) {
260             b.append("synthetic ");
261         }
262         return b.toString().trim();
263     }
264 
265     /**
266      * Returns the integer value (mask) corresponding to the specified access flag.
267      *
268      * @param accessFlag access flag.
269      * @return the integer value (mask) corresponding to the specified access flag.
270      */
271     public static int accessFlagToInt(String accessFlag) {
272         int flag = 0;
273         if (accessFlag.equals("public")) {
274             flag = ACC_PUBLIC;
275         } else if (accessFlag.equals("private")) {
276             flag = ACC_PRIVATE;
277         } else if (accessFlag.equals("protected")) {
278             flag = ACC_PROTECTED;
279         } else if (accessFlag.equals("static")) {
280             flag = ACC_STATIC;
281         } else if (accessFlag.equals("final")) {
282             flag = ACC_FINAL;
283         } else if (accessFlag.equals("super")) {
284             flag = ACC_SUPER;
285         } else if (accessFlag.equals("synchronized")) {
286             flag = ACC_SYNCHRONIZED;
287         } else if (accessFlag.equals("volatile")) {
288             flag = ACC_VOLATILE;
289         } else if (accessFlag.equals("bridge")) {
290             flag = ACC_BRIDGE;
291         } else if (accessFlag.equals("transient")) {
292             flag = ACC_TRANSIENT;
293         } else if (accessFlag.equals("varargs")) {
294             flag = ACC_VARARGS;
295         } else if (accessFlag.equals("native")) {
296             flag = ACC_NATIVE;
297         } else if (accessFlag.equals("interface")) {
298             flag = ACC_INTERFACE;
299         } else if (accessFlag.equals("abstract")) {
300             flag = ACC_ABSTRACT;
301         } else if (accessFlag.equals("strict")) {
302             flag = ACC_STRICT;
303         } else if (accessFlag.equals("synthetic")) {
304             flag = ACC_SYNTHETIC;
305         } else if (accessFlag.equals("annotation")) {
306             flag = ACC_ANNOTATION;
307         } else if (accessFlag.equals("enum")) {
308             flag = ACC_ENUM;
309         }
310         return flag;
311     }
312 }
313