StackMapType.java

  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. package org.apache.bcel.classfile;

  18. import java.io.DataInput;
  19. import java.io.DataOutputStream;
  20. import java.io.IOException;

  21. import org.apache.bcel.Const;

  22. /**
  23.  * This class represents the type of a local variable or item on stack used in the StackMap entries.
  24.  *
  25.  * @see StackMapEntry
  26.  * @see StackMap
  27.  * @see Const
  28.  */
  29. public final class StackMapType implements Node, Cloneable {

  30.     public static final StackMapType[] EMPTY_ARRAY = {}; // BCELifier code generator writes calls to constructor translating null to EMPTY_ARRAY

  31.     private byte type;
  32.     private int index = -1; // Index to CONSTANT_Class or offset
  33.     private ConstantPool constantPool;

  34.     /**
  35.      * @param type type tag as defined in the Constants interface
  36.      * @param index index to constant pool, or byte code offset
  37.      */
  38.     public StackMapType(final byte type, final int index, final ConstantPool constantPool) {
  39.         this.type = checkType(type);
  40.         this.index = index;
  41.         this.constantPool = constantPool;
  42.     }

  43.     /**
  44.      * Constructs object from file stream.
  45.      *
  46.      * @param file Input stream
  47.      * @throws IOException if an I/O error occurs.
  48.      */
  49.     StackMapType(final DataInput file, final ConstantPool constantPool) throws IOException {
  50.         this(file.readByte(), -1, constantPool);
  51.         if (hasIndex()) {
  52.             this.index = file.readUnsignedShort();
  53.         }
  54.         this.constantPool = constantPool;
  55.     }

  56.     /**
  57.      * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
  58.      * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
  59.      *
  60.      * @param v Visitor object
  61.      * @since 6.8.0
  62.      */
  63.     @Override
  64.     public void accept(final Visitor v) {
  65.         v.visitStackMapType(this);
  66.     }

  67.     private byte checkType(final byte type) {
  68.         if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) {
  69.             throw new ClassFormatException("Illegal type for StackMapType: " + type);
  70.         }
  71.         return type;
  72.     }

  73.     /**
  74.      * @return deep copy of this object
  75.      */
  76.     public StackMapType copy() {
  77.         try {
  78.             return (StackMapType) clone();
  79.         } catch (final CloneNotSupportedException e) {
  80.             // TODO should this throw?
  81.         }
  82.         return null;
  83.     }

  84.     /**
  85.      * Dump type entries to file.
  86.      *
  87.      * @param file Output file stream
  88.      * @throws IOException if an I/O error occurs.
  89.      */
  90.     public void dump(final DataOutputStream file) throws IOException {
  91.         file.writeByte(type);
  92.         if (hasIndex()) {
  93.             file.writeShort(getIndex());
  94.         }
  95.     }

  96.     /**
  97.      * Gets the class name of this StackMapType from the constant pool at index position.
  98.      * @return the fully qualified name of the class for this StackMapType.
  99.      * @since 6.8.0
  100.      */
  101.     public String getClassName() {
  102.         return constantPool.constantToString(index, Const.CONSTANT_Class);
  103.     }

  104.     /**
  105.      * @return Constant pool used by this object.
  106.      */
  107.     public ConstantPool getConstantPool() {
  108.         return constantPool;
  109.     }

  110.     /**
  111.      * @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1
  112.      *         otherwise
  113.      */
  114.     public int getIndex() {
  115.         return index;
  116.     }

  117.     public byte getType() {
  118.         return type;
  119.     }

  120.     /**
  121.      * @return true, if type is either ITEM_Object or ITEM_NewObject
  122.      */
  123.     public boolean hasIndex() {
  124.         return type == Const.ITEM_Object || type == Const.ITEM_NewObject;
  125.     }

  126.     private String printIndex() {
  127.         if (type == Const.ITEM_Object) {
  128.             if (index < 0) {
  129.                 return ", class=<unknown>";
  130.             }
  131.             return ", class=" + getClassName();
  132.         }
  133.         if (type == Const.ITEM_NewObject) {
  134.             return ", offset=" + index;
  135.         }
  136.         return "";
  137.     }

  138.     /**
  139.      * @param constantPool Constant pool to be used for this object.
  140.      */
  141.     public void setConstantPool(final ConstantPool constantPool) {
  142.         this.constantPool = constantPool;
  143.     }

  144.     public void setIndex(final int index) {
  145.         this.index = index;
  146.     }

  147.     public void setType(final byte type) {
  148.         this.type = checkType(type);
  149.     }

  150.     /**
  151.      * @return String representation
  152.      */
  153.     @Override
  154.     public String toString() {
  155.         return "(type=" + Const.getItemName(type) + printIndex() + ")";
  156.     }
  157. }