1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.classfile;
  23 
  24 
  25 import com.sun.org.apache.bcel.internal.Constants;
  26 import java.io.*;
  27 import java.util.*;
  28 
  29 /**
  30  * This class represents a reference to an unknown (i.e.,
  31  * application-specific) attribute of a class.  It is instantiated from the
  32  * <em>Attribute.readAttribute()</em> method.  Applications that need to
  33  * read in application-specific attributes should create an <a
  34  * href="./AttributeReader.html">AttributeReader</a> implementation and
  35  * attach it via <a
  36  * href="./Attribute.html#addAttributeReader(java.lang.String,
  37  * com.sun.org.apache.bcel.internal.classfile.AttributeReader)">Attribute.addAttributeReader</a>.
  38 
  39  *
  40  * @see com.sun.org.apache.bcel.internal.classfile.Attribute
  41  * @see com.sun.org.apache.bcel.internal.classfile.AttributeReader
  42  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  43  */
  44 public final class Unknown extends Attribute {
  45   private byte[] bytes;
  46   private String name;
  47 
  48   private static HashMap unknown_attributes = new HashMap();
  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 
  56     for(int i=0; entries.hasNext(); i++)
  57       unknowns[i] = (Unknown)entries.next();
  58 
  59     unknown_attributes.clear();
  60     return unknowns;
  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    * Create a non-standard attribute.
  73    *
  74    * @param name_index Index in constant pool
  75    * @param length Content length in bytes
  76    * @param bytes Attribute contents
  77    * @param constant_pool Array of constants
  78    */
  79   public Unknown(int name_index, int length, byte[] bytes,
  80                  ConstantPool constant_pool)
  81   {
  82     super(Constants.ATTR_UNKNOWN, name_index, length, constant_pool);
  83     this.bytes = bytes;
  84 
  85     name = ((ConstantUtf8)constant_pool.getConstant(name_index,
  86                                                     Constants.CONSTANT_Utf8)).getBytes();
  87     unknown_attributes.put(name, this);
  88   }
  89 
  90   /**
  91    * Construct object from file stream.
  92    * @param name_index Index in constant pool
  93    * @param length Content length in bytes
  94    * @param file Input stream
  95    * @param constant_pool Array of constants
  96    * @throws IOException
  97    */
  98   Unknown(int name_index, int length, DataInputStream file,
  99           ConstantPool constant_pool)
 100        throws IOException
 101   {
 102     this(name_index, length, (byte [])null, constant_pool);
 103 
 104     if(length > 0) {
 105       bytes = new byte[length];
 106       file.readFully(bytes);
 107     }
 108   }
 109 
 110   /**
 111    * Called by objects that are traversing the nodes of the tree implicitely
 112    * defined by the contents of a Java class. I.e., the hierarchy of methods,
 113    * fields, attributes, etc. spawns a tree of objects.
 114    *
 115    * @param v Visitor object
 116    */
 117   public void accept(Visitor v) {
 118     v.visitUnknown(this);
 119   }
 120   /**
 121    * Dump unknown bytes to file stream.
 122    *
 123    * @param file Output file stream
 124    * @throws IOException
 125    */
 126   public final void dump(DataOutputStream file) throws IOException
 127   {
 128     super.dump(file);
 129     if(length > 0)
 130       file.write(bytes, 0, length);
 131   }
 132   /**
 133    * @return data bytes.
 134    */
 135   public final byte[] getBytes() { return bytes; }
 136 
 137   /**
 138    * @return name of attribute.
 139    */
 140   public final String getName() { return name; }
 141 
 142   /**
 143    * @param bytes.
 144    */
 145   public final void setBytes(byte[] bytes) {
 146     this.bytes = bytes;
 147   }
 148 
 149   /**
 150    * @return String representation.
 151    */
 152   public final String toString() {
 153     if(length == 0 || bytes == null)
 154       return "(Unknown attribute " + name + ")";
 155 
 156     String hex;
 157     if(length > 10) {
 158       byte[] tmp = new byte[10];
 159       System.arraycopy(bytes, 0, tmp, 0, 10);
 160       hex = Utility.toHexString(tmp) + "... (truncated)";
 161     }
 162     else
 163       hex = Utility.toHexString(bytes);
 164 
 165     return "(Unknown attribute " + name + ": " + hex + ")";
 166   }
 167 
 168   /**
 169    * @return deep copy of this attribute
 170    */
 171   public Attribute copy(ConstantPool constant_pool) {
 172     Unknown c = (Unknown)clone();
 173 
 174     if(bytes != null)
 175       c.bytes = (byte[])bytes.clone();
 176 
 177     c.constant_pool = constant_pool;
 178     return c;
 179   }
 180 }