001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.bcel.classfile; 021 022import java.io.DataInput; 023import java.io.DataOutputStream; 024import java.io.IOException; 025import java.util.Arrays; 026import java.util.Iterator; 027import java.util.stream.Stream; 028 029import org.apache.bcel.Const; 030import org.apache.bcel.util.Args; 031 032// The new table is used when generic types are about... 033 034//LocalVariableTable_attribute { 035// u2 attribute_name_index; 036// u4 attribute_length; 037// u2 local_variable_table_length; 038// { u2 start_pc; 039// u2 length; 040// u2 name_index; 041// u2 descriptor_index; 042// u2 index; 043// } local_variable_table[local_variable_table_length]; 044// } 045 046//LocalVariableTypeTable_attribute { 047// u2 attribute_name_index; 048// u4 attribute_length; 049// u2 local_variable_type_table_length; 050// { 051// u2 start_pc; 052// u2 length; 053// u2 name_index; 054// u2 signature_index; 055// u2 index; 056// } localVariableTypeTable[local_variable_type_table_length]; 057// } 058// J5TODO: Needs some testing ! 059 060/** 061 * Represents the LocalVariableTypeTable attribute. 062 * 063 * @since 6.0 064 */ 065public class LocalVariableTypeTable extends Attribute implements Iterable<LocalVariable> { 066 067 private static final LocalVariable[] EMPTY_ARRAY = {}; 068 069 private LocalVariable[] localVariableTypeTable; // variables 070 071 LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException { 072 this(nameIdx, len, (LocalVariable[]) null, cpool); 073 final int localVariableTypeTableLength = input.readUnsignedShort(); 074 localVariableTypeTable = new LocalVariable[localVariableTypeTableLength]; 075 for (int i = 0; i < localVariableTypeTableLength; i++) { 076 localVariableTypeTable[i] = new LocalVariable(input, cpool); 077 } 078 } 079 080 public LocalVariableTypeTable(final int nameIndex, final int length, final LocalVariable[] localVariableTypeTable, final ConstantPool constantPool) { 081 super(Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE, nameIndex, length, constantPool); 082 this.localVariableTypeTable = localVariableTypeTable != null ? localVariableTypeTable : LocalVariable.EMPTY_ARRAY; 083 Args.requireU2(this.localVariableTypeTable.length, "localVariableTypeTable.length"); 084 } 085 086 public LocalVariableTypeTable(final LocalVariableTypeTable c) { 087 this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), c.getConstantPool()); 088 } 089 090 @Override 091 public void accept(final Visitor v) { 092 v.visitLocalVariableTypeTable(this); 093 } 094 095 /** 096 * @return deep copy of this attribute. 097 */ 098 @Override 099 public Attribute copy(final ConstantPool constantPool) { 100 final LocalVariableTypeTable c = (LocalVariableTypeTable) clone(); 101 c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length]; 102 Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy()); 103 c.setConstantPool(constantPool); 104 return c; 105 } 106 107 @Override 108 public final void dump(final DataOutputStream file) throws IOException { 109 super.dump(file); 110 file.writeShort(localVariableTypeTable.length); 111 for (final LocalVariable variable : localVariableTypeTable) { 112 variable.dump(file); 113 } 114 } 115 116 public final LocalVariable getLocalVariable(final int index) { 117 for (final LocalVariable variable : localVariableTypeTable) { 118 if (variable.getIndex() == index) { 119 return variable; 120 } 121 } 122 return null; 123 } 124 125 public final LocalVariable[] getLocalVariableTypeTable() { 126 return localVariableTypeTable; 127 } 128 129 public final int getTableLength() { 130 return localVariableTypeTable == null ? 0 : localVariableTypeTable.length; 131 } 132 133 @Override 134 public Iterator<LocalVariable> iterator() { 135 return Stream.of(localVariableTypeTable).iterator(); 136 } 137 138 public final void setLocalVariableTable(final LocalVariable[] localVariableTable) { 139 this.localVariableTypeTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY; 140 } 141 142 /** 143 * @return String representation. 144 */ 145 @Override 146 public final String toString() { 147 final StringBuilder buf = new StringBuilder(); 148 for (int i = 0; i < localVariableTypeTable.length; i++) { 149 buf.append(localVariableTypeTable[i].toStringShared(true)); 150 if (i < localVariableTypeTable.length - 1) { 151 buf.append('\n'); 152 } 153 } 154 return buf.toString(); 155 } 156}