1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 }