View Javadoc

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