View Javadoc

1   /*
2    * Copyright  2000-2004 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  package org.apache.bcel.classfile;
18  
19  import java.io.DataInputStream;
20  import java.io.DataOutputStream;
21  import java.io.IOException;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.Map;
25  import org.apache.bcel.Constants;
26  
27  /***
28   * This class represents a reference to an unknown (i.e.,
29   * application-specific) attribute of a class.  It is instantiated from the
30   * <em>Attribute.readAttribute()</em> method.  Applications that need to
31   * read in application-specific attributes should create an <a
32   * href="./AttributeReader.html">AttributeReader</a> implementation and
33   * attach it via <a
34   * href="./Attribute.html#addAttributeReader(java.lang.String,
35   * org.apache.bcel.classfile.AttributeReader)">Attribute.addAttributeReader</a>.
36  
37   *
38   * @version $Id: Unknown.java 386056 2006-03-15 11:31:56Z tcurdt $
39   * @see org.apache.bcel.classfile.Attribute
40   * @see org.apache.bcel.classfile.AttributeReader
41   * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
42   */
43  public final class Unknown extends Attribute {
44  
45      private byte[] bytes;
46      private String name;
47      private static Map unknown_attributes = new HashMap();
48  
49  
50      /*** @return array of unknown attributes, but just one for each kind.
51       */
52      static Unknown[] getUnknownAttributes() {
53          Unknown[] unknowns = new Unknown[unknown_attributes.size()];
54          Iterator entries = unknown_attributes.values().iterator();
55          for (int i = 0; entries.hasNext(); i++) {
56              unknowns[i] = (Unknown) entries.next();
57          }
58          unknown_attributes.clear();
59          return unknowns;
60      }
61  
62  
63      /***
64       * Initialize from another object. Note that both objects use the same
65       * references (shallow copy). Use clone() for a physical copy.
66       */
67      public Unknown(Unknown c) {
68          this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
69      }
70  
71  
72      /***
73       * Create a non-standard attribute.
74       *
75       * @param name_index Index in constant pool
76       * @param length Content length in bytes
77       * @param bytes Attribute contents
78       * @param constant_pool Array of constants
79       */
80      public Unknown(int name_index, int length, byte[] bytes, ConstantPool constant_pool) {
81          super(Constants.ATTR_UNKNOWN, name_index, length, constant_pool);
82          this.bytes = bytes;
83          name = ((ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8))
84                  .getBytes();
85          unknown_attributes.put(name, this);
86      }
87  
88  
89      /***
90       * Construct object from file stream.
91       * @param name_index Index in constant pool
92       * @param length Content length in bytes
93       * @param file Input stream
94       * @param constant_pool Array of constants
95       * @throws IOException
96       */
97      Unknown(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
98              throws IOException {
99          this(name_index, length, (byte[]) null, constant_pool);
100         if (length > 0) {
101             bytes = new byte[length];
102             file.readFully(bytes);
103         }
104     }
105 
106 
107     /***
108      * Called by objects that are traversing the nodes of the tree implicitely
109      * defined by the contents of a Java class. I.e., the hierarchy of methods,
110      * fields, attributes, etc. spawns a tree of objects.
111      *
112      * @param v Visitor object
113      */
114     public void accept( Visitor v ) {
115         v.visitUnknown(this);
116     }
117 
118 
119     /***
120      * Dump unknown bytes to file stream.
121      *
122      * @param file Output file stream
123      * @throws IOException
124      */
125     public final void dump( DataOutputStream file ) throws IOException {
126         super.dump(file);
127         if (length > 0) {
128             file.write(bytes, 0, length);
129         }
130     }
131 
132 
133     /***
134      * @return data bytes.
135      */
136     public final byte[] getBytes() {
137         return bytes;
138     }
139 
140 
141     /***
142      * @return name of attribute.
143      */
144     public final String getName() {
145         return name;
146     }
147 
148 
149     /***
150      * @param bytes the bytes to set
151      */
152     public final void setBytes( byte[] bytes ) {
153         this.bytes = bytes;
154     }
155 
156 
157     /***
158      * @return String representation.
159      */
160     public final String toString() {
161         if (length == 0 || bytes == null) {
162             return "(Unknown attribute " + name + ")";
163         }
164         String hex;
165         if (length > 10) {
166             byte[] tmp = new byte[10];
167             System.arraycopy(bytes, 0, tmp, 0, 10);
168             hex = Utility.toHexString(tmp) + "... (truncated)";
169         } else {
170             hex = Utility.toHexString(bytes);
171         }
172         return "(Unknown attribute " + name + ": " + hex + ")";
173     }
174 
175 
176     /***
177      * @return deep copy of this attribute
178      */
179     public Attribute copy( ConstantPool _constant_pool ) {
180         Unknown c = (Unknown) clone();
181         if (bytes != null) {
182             c.bytes = new byte[bytes.length];
183             System.arraycopy(bytes, 0, c.bytes, 0, bytes.length);
184         }
185         c.constant_pool = _constant_pool;
186         return c;
187     }
188 }