View Javadoc

1   /*
2    * Copyright 2005 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at 
7    * 
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software 
11   * distributed under the License is distributed on an "AS IS" BASIS, 
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License.
15   */
16  
17  
18  package org.apache.jdo.impl.enhancer.classfile;
19  
20  import java.io.*;
21  import java.util.Vector;
22  import java.util.Stack;
23  import java.util.Arrays;
24  import java.util.Comparator;
25  import java.util.Enumeration;
26  import java.util.NoSuchElementException;
27  
28  /***
29   * A list of attributes within a class file.
30   * These lists occur in several places within a class file
31   *    - at class level
32   *    - at method level
33   *    - at field level
34   *    - at attribute level
35   */
36  public class AttributeVector {
37  
38      /* Vector of ClassAttribute */
39      private ClassAttribute attributes[] = null;
40  
41      /***
42       * Returns the i'th attribute in the array
43       */
44      private ClassAttribute attrAt(int i) {
45          return attributes[i];
46      }
47  
48      /***
49       * Construct an empty AttributeVector
50       */
51      public AttributeVector() { }
52  
53      /***
54       * Add an element to the vector
55       */
56      public void addElement(ClassAttribute attr) {
57          if (attributes == null)
58              attributes = new ClassAttribute[1];
59          else {
60              ClassAttribute newAttributes[] = new ClassAttribute[attributes.length+1];
61              System.arraycopy(attributes, 0, newAttributes, 0, attributes.length);
62              attributes = newAttributes;
63          }
64          attributes[attributes.length-1] = attr;
65      }
66  
67      public Enumeration elements() {
68          class AttributeVectorEnumeration implements Enumeration {
69              private ClassAttribute[] attributes;
70              private int current = 0;
71  
72              AttributeVectorEnumeration(ClassAttribute attrs[]) {
73                  attributes = attrs;
74              }
75  
76              public boolean hasMoreElements() {
77                  return attributes != null && current < attributes.length;
78              }
79              public Object nextElement() {
80                  if (!hasMoreElements())
81                      throw new NoSuchElementException();
82                  return attributes[current++];
83              }
84          }
85  
86          return new AttributeVectorEnumeration(attributes);
87      }
88  
89      /***
90       * Look for an attribute of a specific name
91       */
92      public ClassAttribute findAttribute(String attrName) {
93          Enumeration e = elements();
94          while (e.hasMoreElements()) {
95              ClassAttribute attr = (ClassAttribute) e.nextElement();
96              if (attr.attrName().asString().equals(attrName))
97                  return attr;
98          }
99          return null;
100     }
101 
102     /***
103      * Compares this instance with another for structural equality.
104      */
105     //@olsen: added method
106     public boolean isEqual(Stack msg, Object obj) {
107         if (!(obj instanceof AttributeVector)) {
108             msg.push("obj/obj.getClass() = "
109                      + (obj == null ? null : obj.getClass()));
110             msg.push("this.getClass() = "
111                      + this.getClass());
112             return false;
113         }
114         AttributeVector other = (AttributeVector)obj;
115 
116         if (this.attributes.length != other.attributes.length) {
117             msg.push("attributes.length "
118                      + String.valueOf(other.attributes.length));
119             msg.push("attributes.length "
120                      + String.valueOf(this.attributes.length));
121             return false;
122         }
123 
124         // sort attributes by name
125         class ClassAttributeComparator implements Comparator {
126             public int compare(Object o1, Object o2) {
127                 ClassAttribute a1 = (ClassAttribute)o1;
128                 ClassAttribute a2 = (ClassAttribute)o2;
129                 String s1 = a1.attrName().asString();
130                 String s2 = a2.attrName().asString();
131                 return s1.compareTo(s2);
132             }
133         }
134         ClassAttributeComparator comparator = new ClassAttributeComparator();
135         ClassAttribute[] thisAttributes
136             = (ClassAttribute[])this.attributes.clone();
137         ClassAttribute[] otherAttributes
138             = (ClassAttribute[])other.attributes.clone();
139         Arrays.sort(thisAttributes, comparator);
140         Arrays.sort(otherAttributes, comparator);
141         for (int i = 0; i < attributes.length; i++) {
142             ClassAttribute a1 = thisAttributes[i];
143             ClassAttribute a2 = otherAttributes[i];
144             if (!a1.isEqual(msg, a2)) {
145                 msg.push("attributes[i] = " + String.valueOf(a2));
146                 msg.push("attributes[i] = " + String.valueOf(a1));
147                 return false;
148             }
149         }
150         return true;
151     }
152 
153     /***
154      * General attribute reader
155      */
156     static AttributeVector readAttributes(
157 	DataInputStream data, ConstantPool constantPool)
158 	throws IOException {
159         AttributeVector attribs = new AttributeVector();
160         int n_attrs = data.readUnsignedShort();
161         while (n_attrs-- > 0) {
162             attribs.addElement(ClassAttribute.read(data, constantPool));
163         }
164         return attribs;
165     }
166 
167     /***
168      * ClassMethod attribute reader
169      */
170     static AttributeVector readAttributes(
171 	DataInputStream data, CodeEnv codeEnv)
172 	throws IOException {
173         AttributeVector attribs = new AttributeVector();
174         int n_attrs = data.readUnsignedShort();
175         while (n_attrs-- > 0) {
176             attribs.addElement(ClassAttribute.read(data, codeEnv));
177         }
178         return attribs;
179     }
180 
181     /***
182      * Write the attributes to the output stream
183      */
184     void write(DataOutputStream out) throws IOException {
185         if (attributes == null) {
186             out.writeShort(0);
187         } else {
188             out.writeShort(attributes.length);
189             for (int i=0; i<attributes.length; i++)
190                 attributes[i].write(out);
191         }
192     }
193 
194     /***
195      * Print a description of the attributes
196      */
197     void print(PrintStream out, int indent) {
198         if (attributes != null) {
199             for (int i=0; i<attributes.length; i++)
200                 attributes[i].print(out, indent);
201         }
202     }
203 
204     /***
205      * Print a brief summary of the attributes
206      */
207     //@olsen: added 'out' and 'indent' parameters
208     void summarize(PrintStream out, int indent) {
209         ClassPrint.spaces(out, indent);
210         out.println((attributes == null ? 0 : attributes.length) +
211                            " attributes");
212     }
213 }