001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.classfile; 019 020import java.io.DataInput; 021import java.io.DataOutputStream; 022import java.io.IOException; 023 024import org.apache.bcel.Const; 025 026/** 027 * This class represents a stack map attribute used for 028 * preverification of Java classes for the <a 029 * href="http://java.sun.com/j2me/"> Java 2 Micro Edition</a> 030 * (J2ME). This attribute is used by the <a 031 * href="http://java.sun.com/products/cldc/">KVM</a> and contained 032 * within the Code attribute of a method. See CLDC specification 033 * �5.3.1.2 034 * 035 * @see Code 036 * @see StackMapEntry 037 * @see StackMapType 038 */ 039public final class StackMap extends Attribute { 040 041 private StackMapEntry[] map; // Table of stack map entries 042 043 044 /* 045 * @param name_index Index of name 046 * @param length Content length in bytes 047 * @param map Table of stack map entries 048 * @param constant_pool Array of constants 049 */ 050 public StackMap(final int name_index, final int length, final StackMapEntry[] map, final ConstantPool constant_pool) { 051 super(Const.ATTR_STACK_MAP, name_index, length, constant_pool); 052 this.map = map; 053 } 054 055 056 /** 057 * Construct object from input stream. 058 * 059 * @param name_index Index of name 060 * @param length Content length in bytes 061 * @param input Input stream 062 * @param constant_pool Array of constants 063 * @throws IOException 064 */ 065 StackMap(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { 066 this(name_index, length, (StackMapEntry[]) null, constant_pool); 067 final int map_length = input.readUnsignedShort(); 068 map = new StackMapEntry[map_length]; 069 for (int i = 0; i < map_length; i++) { 070 map[i] = new StackMapEntry(input, constant_pool); 071 } 072 } 073 074 075 /** 076 * Dump stack map table attribute to file stream in binary format. 077 * 078 * @param file Output file stream 079 * @throws IOException 080 */ 081 @Override 082 public void dump( final DataOutputStream file ) throws IOException { 083 super.dump(file); 084 file.writeShort(map.length); 085 for (final StackMapEntry entry : map) { 086 entry.dump(file); 087 } 088 } 089 090 091 /** 092 * @return Array of stack map entries 093 */ 094 public StackMapEntry[] getStackMap() { 095 return map; 096 } 097 098 099 /** 100 * @param map Array of stack map entries 101 */ 102 public void setStackMap( final StackMapEntry[] map ) { 103 this.map = map; 104 int len = 2; // Length of 'number_of_entries' field prior to the array of stack maps 105 for (final StackMapEntry element : map) { 106 len += element.getMapEntrySize(); 107 } 108 setLength(len); 109 } 110 111 112 /** 113 * @return String representation. 114 */ 115 @Override 116 public String toString() { 117 final StringBuilder buf = new StringBuilder("StackMap("); 118 for (int i = 0; i < map.length; i++) { 119 buf.append(map[i]); 120 if (i < map.length - 1) { 121 buf.append(", "); 122 } 123 } 124 buf.append(')'); 125 return buf.toString(); 126 } 127 128 129 /** 130 * @return deep copy of this attribute 131 */ 132 @Override 133 public Attribute copy( final ConstantPool _constant_pool ) { 134 final StackMap c = (StackMap) clone(); 135 c.map = new StackMapEntry[map.length]; 136 for (int i = 0; i < map.length; i++) { 137 c.map[i] = map[i].copy(); 138 } 139 c.setConstantPool(_constant_pool); 140 return c; 141 } 142 143 144 /** 145 * Called by objects that are traversing the nodes of the tree implicitely 146 * defined by the contents of a Java class. I.e., the hierarchy of methods, 147 * fields, attributes, etc. spawns a tree of objects. 148 * 149 * @param v Visitor object 150 */ 151 @Override 152 public void accept( final Visitor v ) { 153 v.visitStackMap(this); 154 } 155 156 157 public int getMapLength() { 158 return map == null ? 0 : map.length; 159 } 160}