Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/techtrader/modules/tools/bytecode/InnerClassesAttribute.java


1   package com.techtrader.modules.tools.bytecode;
2   
3   
4   import java.io.DataOutput;
5   import java.io.DataInput;
6   import java.io.IOException;
7   import java.util.List;
8   import java.util.LinkedList;
9   import java.util.Iterator;
10  
11  import com.techtrader.modules.tools.bytecode.visitor.BCVisitor;
12  
13  
14  /**
15   *  Attribute describing the inner classes of a .class file.  Note: for
16   *  methods that take in the name of the inner class, this refers to the
17   *  short name it is referred to be within the owning class, not the full
18   *  name.  For anonymous inner classes, use the empty String.
19   *  TODO: Import and copy methods are broken.
20   *  
21   *  @author    Abe White
22   */
23  public class InnerClassesAttribute
24    extends Attribute
25  {
26    private List _innerClasses = new LinkedList ();
27  
28  
29    /**
30     *  Protected constructor.
31     */
32    public InnerClassesAttribute (int nameIndex, BCEntity owner)
33    {
34      super (nameIndex, owner);
35    }
36  
37  
38    /**
39     *  Get all the inner classes owned by this entity.
40     *
41     *  @return    all owned inner classes, or empty array if none
42     */
43    public InnerClass[] getInnerClasses ()
44    {
45      return (InnerClass[]) _innerClasses.toArray 
46        (new InnerClass[_innerClasses.size ()]);
47    }
48  
49  
50    /**
51     *  Return the inner class with the given name.  If multiple inner classes
52     *  share the name, which is returned is undefined.
53     */
54    public InnerClass getInnerClass (String name)
55    {
56      InnerClass next;
57      for (Iterator i = _innerClasses.iterator (); i.hasNext ();)
58      {
59        next = (InnerClass) i.next ();
60        if (next.getName ().equals (name))
61          return next;
62      }
63  
64      return null;
65    }
66  
67    
68    /**
69     *  Returns all inner classes with the given name.
70      *
71     *  @return    the matching inner classes, or empty array if none
72     */
73    public InnerClass[] getInnerClasses (String name)
74    {
75      List matches = new LinkedList ();
76  
77      InnerClass next;
78      for (Iterator i = _innerClasses.iterator (); i.hasNext ();)
79      {
80        next = (InnerClass) i.next ();
81        if (next.getName ().equals (name))
82          matches.add (next);
83      }
84  
85      return (InnerClass[]) matches.toArray (new InnerClass[matches.size ()]);
86    }
87  
88  
89    /**
90     *  Import an inner class from another entity, or make a copy of one
91     *  on this entity.
92     */
93    public InnerClass importInnerClass (InnerClass inner)
94    {
95      InnerClass newInner = addInnerClass (inner.getName ());
96      newInner.setAccessFlags (inner.getAccessFlags ());
97      
98      return newInner;
99    }
100 
101 
102   /**
103    *  Import all inner classes from another entity.
104    */
105   public void importInnerClasses (InnerClassesAttribute other)
106   {
107     if (other == null)
108       return;
109 
110     InnerClass[] inners = other.getInnerClasses ();
111     for (int i = 0; i < inners.length; i++)
112       importInnerClass (inners[i]);
113   }
114 
115 
116   /**
117    *  Add an inner class.
118    */
119   public InnerClass addInnerClass ()
120   {
121     InnerClass inner = new InnerClass (this);
122     _innerClasses.add (inner);
123 
124     return inner;
125   }
126 
127 
128   /**  
129     *  Add an inner class with the given name.
130    */
131   public InnerClass addInnerClass (String name)
132   {
133     InnerClass inner = new InnerClass (name, this);
134     _innerClasses.add (inner);
135 
136     return inner;
137   }
138 
139 
140   /**
141    *  Clear all inner classes from this entity.
142    */
143   public void clearInnerClasses ()
144   {
145     _innerClasses.clear ();
146   }
147 
148 
149   /**
150    *  Remove all inner classes with the given name from the list.
151    *
152    *  @return    true if an inner class was removed, false otherwise
153    */
154   public boolean removeInnerClass (String name)
155   {
156     InnerClass[] matches = getInnerClasses (name);
157     for (int i = 0; i < matches.length; i++)
158       removeInnerClass (matches[i]);
159 
160     return (matches.length > 0);
161   }
162 
163 
164   /**
165    *  Remove the given inner class.  After being removed, the given InnerClass
166    *  is invalid, and the result of any operations on it are undefined.
167    *
168    *  @return    true if the inner class was removed, false otherwise
169    */
170   public boolean removeInnerClass (InnerClass innerClass)
171   {
172     if (innerClass == null || !_innerClasses.remove (innerClass))
173       return false;
174 
175     innerClass.invalidate ();
176     return true;
177   }
178 
179 
180   public int getLength ()
181   {
182     return 2 + 8 * _innerClasses.size ();
183   }
184 
185 
186   protected void copy (Attribute other)
187   {
188     importInnerClasses ((InnerClassesAttribute) other);  
189   }
190 
191 
192   protected void readData (DataInput in, int length)
193     throws IOException
194   {
195     _innerClasses.clear ();
196     int numInnerClasses = in.readUnsignedShort ();
197 
198     InnerClass innerClass;
199     for (int i = 0; i < numInnerClasses; i++)
200     {
201       innerClass = addInnerClass ();
202       innerClass.readData (in);
203     }
204   }
205 
206 
207   protected void writeData (DataOutput out, int length)
208     throws IOException
209   {
210     out.writeShort (_innerClasses.size ());
211     for (Iterator i = _innerClasses.iterator (); i.hasNext ();)
212       ((InnerClass) i.next ()).writeData (out);
213   }
214 
215 
216   public void acceptVisit (BCVisitor visit)
217   {
218     visit.enterInnerClassesAttribute (this);  
219     
220     for (Iterator i = _innerClasses.iterator (); i.hasNext ();)
221       ((InnerClass) i.next ()).acceptVisit (visit);
222 
223     visit.exitInnerClassesAttribute (this);  
224   }
225 }