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 }