View Javadoc

1   package serp.bytecode;
2   
3   import java.io.*;
4   
5   import serp.bytecode.lowlevel.*;
6   import serp.bytecode.visitor.*;
7   import serp.util.*;
8   
9   /***
10   * Any referenced class that is not a package member is represented by
11   * this structure. This includes member classes and interfaces.
12   *
13   * @author Abe White
14   */
15  public class InnerClass implements BCEntity, VisitAcceptor {
16      private int _index = 0;
17      private int _nameIndex = 0;
18      private int _ownerIndex = 0;
19      private int _access = Constants.ACCESS_PRIVATE;
20      private InnerClasses _owner = null;
21  
22      InnerClass(InnerClasses owner) {
23          _owner = owner;
24      }
25  
26      /***
27       * Inner classes are stored in an {@link InnerClasses} attribute.
28       */
29      public InnerClasses getOwner() {
30          return _owner;
31      }
32  
33      void invalidate() {
34          _owner = null;
35      }
36  
37      /////////////////////
38      // Access operations
39      /////////////////////
40  
41      /***
42       * Return the access flags of the inner class.
43       */
44      public int getAccessFlags() {
45          return _access;
46      }
47  
48      /***
49       * Set the access flags of the inner class.
50       */
51      public void setAccessFlags(int accessFlags) {
52          _access = accessFlags;
53      }
54  
55      /***
56       * Manipulate the inner class access flags.
57       */
58      public boolean isPublic() {
59          return (getAccessFlags() & Constants.ACCESS_PUBLIC) > 0;
60      }
61  
62      /***
63       * Manipulate the inner class access flags.
64       */
65      public void makePublic() {
66          setAccessFlags(getAccessFlags() | Constants.ACCESS_PUBLIC);
67          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE);
68          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED);
69      }
70  
71      /***
72       * Manipulate the inner class access flags.
73       */
74      public boolean isProtected() {
75          return (getAccessFlags() & Constants.ACCESS_PROTECTED) > 0;
76      }
77  
78      /***
79       * Manipulate the inner class access flags.
80       */
81      public void makeProtected() {
82          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC);
83          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE);
84          setAccessFlags(getAccessFlags() | Constants.ACCESS_PROTECTED);
85      }
86  
87      /***
88       * Manipulate the inner class access flags.
89       */
90      public boolean isPrivate() {
91          return (getAccessFlags() & Constants.ACCESS_PRIVATE) > 0;
92      }
93  
94      /***
95       * Manipulate the inner class access flags.
96       */
97      public void makePrivate() {
98          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC);
99          setAccessFlags(getAccessFlags() | Constants.ACCESS_PRIVATE);
100         setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED);
101     }
102 
103     /***
104      * Manipulate the inner class access flags.
105      */
106     public boolean isFinal() {
107         return (getAccessFlags() & Constants.ACCESS_FINAL) > 0;
108     }
109 
110     /***
111      * Manipulate the inner class access flags.
112      */
113     public void setFinal(boolean on) {
114         if (on)
115             setAccessFlags(getAccessFlags() | Constants.ACCESS_FINAL);
116         else
117             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_FINAL);
118     }
119 
120     /***
121      * Manipulate the inner class access flags.
122      */
123     public boolean isStatic() {
124         return (getAccessFlags() & Constants.ACCESS_STATIC) > 0;
125     }
126 
127     /***
128      * Manipulate the inner class access flags.
129      */
130     public void setStatic(boolean on) {
131         if (on)
132             setAccessFlags(getAccessFlags() | Constants.ACCESS_STATIC);
133         else
134             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_STATIC);
135     }
136 
137     /***
138      * Manipulate the class access flags.
139      */
140     public boolean isInterface() {
141         return (getAccessFlags() & Constants.ACCESS_INTERFACE) > 0;
142     }
143 
144     /***
145      * Manipulate the class access flags.
146      */
147     public void setInterface(boolean on) {
148         if (on) {
149             setAccessFlags(getAccessFlags() | Constants.ACCESS_INTERFACE);
150             setAbstract(true);
151         } else
152             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_INTERFACE);
153     }
154 
155     /***
156      * Manipulate the class access flags.
157      */
158     public boolean isAbstract() {
159         return (getAccessFlags() & Constants.ACCESS_ABSTRACT) > 0;
160     }
161 
162     /***
163      * Manipulate the class access flags.
164      */
165     public void setAbstract(boolean on) {
166         if (on)
167             setAccessFlags(getAccessFlags() | Constants.ACCESS_INTERFACE);
168         else
169             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_INTERFACE);
170     }
171 
172     /***
173      * Manipulate the inner class access flags.
174      */
175     public boolean isSynthetic() {
176         return (getAccessFlags() & Constants.ACCESS_SYNTHETIC) > 0;
177     }
178 
179     /***
180      * Manipulate the inner class access flags.
181      */
182     public void setSynthetic(boolean on) {
183         if (on)
184             setAccessFlags(getAccessFlags() | Constants.ACCESS_SYNTHETIC);
185         else
186             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_SYNTHETIC);
187     }
188 
189     /***
190      * Manipulate the inner class access flags.
191      */
192     public boolean isAnnotation() {
193         return (getAccessFlags() & Constants.ACCESS_ANNOTATION) > 0;
194     }
195 
196     /***
197      * Manipulate the inner class access flags.  Setting to true also makes this
198      * an interface.
199      */
200     public void setAnnotation(boolean on) {
201         if (on) {
202             setAccessFlags(getAccessFlags() | Constants.ACCESS_ANNOTATION);
203             setAccessFlags(getAccessFlags() | Constants.ACCESS_INTERFACE);
204         } else
205             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_ANNOTATION);
206     }
207 
208     /***
209      * Manipulate the inner class access flags.
210      */
211     public boolean isEnum() {
212         return (getAccessFlags() & Constants.ACCESS_ENUM) > 0;
213     }
214 
215     /***
216      * Manipulate the inner class access flags.
217      */
218     public void setEnum(boolean on) {
219         if (on)
220             setAccessFlags(getAccessFlags() | Constants.ACCESS_ENUM);
221         else
222             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_ENUM);
223     }
224 
225     ////////////////////////////////
226     // Name, type, owner operations
227     ////////////////////////////////
228 
229     /***
230      * Return the {@link ConstantPool} index of the {@link UTF8Entry} that
231      * describes the simple name this class is referred to in source, or
232      * 0 for anonymous classes.
233      */
234     public int getNameIndex() {
235         return _nameIndex;
236     }
237 
238     /***
239      * Set the {@link ConstantPool} index of the {@link UTF8Entry} that
240      * describes the simple name this class is referred to in source, or
241      * 0 for anonymous classes.
242      */
243     public void setNameIndex(int nameIndex) {
244         _nameIndex = nameIndex;
245     }
246 
247     /***
248      * Return the simple name of this inner class, or null if anonymous.
249      */
250     public String getName() {
251         if (getNameIndex() == 0)
252             return null;
253         return ((UTF8Entry) getPool().getEntry(getNameIndex())).getValue();
254     }
255 
256     /***
257      * Set the simple name of this inner class.
258      */
259     public void setName(String name) {
260         if (name == null)
261             setNameIndex(0);
262         else
263             setNameIndex(getPool().findUTF8Entry(name, true));
264     }
265 
266     /***
267      * Return the {@link ConstantPool} index of the {@link ClassEntry} that
268      * describes this class, or 0 if none.
269      */
270     public int getTypeIndex() {
271         return _index;
272     }
273 
274     /***
275      * Set the {@link ConstantPool} index of the {@link ClassEntry} that
276      * describes this class.
277      */
278     public void setTypeIndex(int index) {
279         _index = index;
280     }
281 
282     /***
283      * Return the full name of the inner class, or null if unset.
284      */
285     public String getTypeName() {
286         if (getTypeIndex() == 0)
287             return null;
288         ClassEntry entry = (ClassEntry) getPool().getEntry(getTypeIndex());
289         return getProject().getNameCache().getExternalForm(entry.getNameEntry().
290             getValue(), false);
291     }
292 
293     /***
294      * Return the type of the inner class.
295      * If the type has not been set, this method will return null.
296      */
297     public Class getType() {
298         String type = getTypeName();
299         if (type == null)
300             return null;
301         return Strings.toClass(type, getClassLoader());
302     }
303 
304     /***
305      * Return the type for this instruction.
306      * If the type has not been set, this method will return null.
307      */
308     public BCClass getTypeBC() {
309         String type = getTypeName();
310         if (type == null)
311             return null;
312         return getProject().loadClass(type, getClassLoader());
313     }
314 
315     /***
316      * Set the type of this inner class.
317      */
318     public void setType(String type) {
319         if (type == null)
320             setTypeIndex(0);
321         else {
322             type = getProject().getNameCache().getInternalForm(type, false);
323             setTypeIndex(getPool().findClassEntry(type, true));
324         }
325     }
326 
327     /***
328      * Set the type of this inner class.
329      */
330     public void setType(Class type) {
331         if (type == null)
332             setType((String) null);
333         else
334             setType(type.getName());
335     }
336 
337     /***
338      * Set the type of this inner class.
339      */
340     public void setType(BCClass type) {
341         if (type == null)
342             setType((String) null);
343         else
344             setType(type.getName());
345     }
346 
347     /***
348      * Return the {@link ConstantPool} index of the {@link ClassEntry} that
349      * describes the declaring class, or 0 if this class is not a member class.
350      */
351     public int getDeclarerIndex() {
352         return _ownerIndex;
353     }
354 
355     /***
356      * Set the {@link ConstantPool} index of the {@link ClassEntry} that
357      * describes the declaring class, or 0 if this class is not a member class.
358      */
359     public void setDeclarerIndex(int ownerIndex) {
360         _ownerIndex = ownerIndex;
361     }
362 
363     /***
364      * Return the full name of the declaring class, or null if unset/not a
365      * member.
366      */
367     public String getDeclarerName() {
368         if (getDeclarerIndex() == 0)
369             return null;
370         ClassEntry entry = (ClassEntry) getPool().getEntry(getDeclarerIndex());
371         return getProject().getNameCache().getExternalForm(entry.getNameEntry().
372             getValue(), false);
373     }
374 
375     /***
376      * Return the type of the declaring class.
377      * If the type has not been set or the class is not a member, this method
378      * will return null.
379      */
380     public Class getDeclarerType() {
381         String type = getDeclarerName();
382         if (type == null)
383             return null;
384         return Strings.toClass(type, getClassLoader());
385     }
386 
387     /***
388      * Return the type for this instruction.
389      * If the type has not been set or the class is not a member, this method
390      * will return null.
391      */
392     public BCClass getDeclarerBC() {
393         String type = getDeclarerName();
394         if (type == null)
395             return null;
396         return getProject().loadClass(type, getClassLoader());
397     }
398 
399     /***
400      * Set the type of this declaring class.
401      */
402     public void setDeclarer(String type) {
403         if (type == null)
404             setDeclarerIndex(0);
405         else {
406             type = getProject().getNameCache().getInternalForm(type, false);
407             setDeclarerIndex(getPool().findClassEntry(type, true));
408         }
409     }
410 
411     /***
412      * Set the type of this declaring class.
413      */
414     public void setDeclarer(Class type) {
415         if (type == null)
416             setDeclarer((String) null);
417         else
418             setDeclarer(type.getName());
419     }
420 
421     /***
422      * Set the type of this declaring class.
423      */
424     public void setDeclarer(BCClass type) {
425         if (type == null)
426             setDeclarer((String) null);
427         else
428             setDeclarer(type.getName());
429     }
430 
431     ///////////////////////////
432     // BCEntity implementation
433     ///////////////////////////
434 
435     public Project getProject() {
436         return _owner.getProject();
437     }
438 
439     public ConstantPool getPool() {
440         return _owner.getPool();
441     }
442 
443     public ClassLoader getClassLoader() {
444         return _owner.getClassLoader();
445     }
446 
447     public boolean isValid() {
448         return _owner != null;
449     }
450 
451     public void acceptVisit(BCVisitor visit) {
452         visit.enterInnerClass(this);
453         visit.exitInnerClass(this);
454     }
455 
456     //////////////////
457     // I/O operations
458     //////////////////
459 
460     void read(DataInput in) throws IOException {
461         setTypeIndex(in.readUnsignedShort());
462         setDeclarerIndex(in.readUnsignedShort());
463         setNameIndex(in.readUnsignedShort());
464         setAccessFlags(in.readUnsignedShort());
465     }
466 
467     void write(DataOutput out) throws IOException {
468         out.writeShort(getTypeIndex());
469         out.writeShort(getDeclarerIndex());
470         out.writeShort(getNameIndex());
471         out.writeShort(getAccessFlags());
472     }
473 }