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; 023import java.util.Arrays; 024import java.util.Iterator; 025import java.util.stream.Stream; 026 027import org.apache.bcel.Const; 028import org.apache.bcel.util.Args; 029 030// The new table is used when generic types are about... 031 032//LocalVariableTable_attribute { 033// u2 attribute_name_index; 034// u4 attribute_length; 035// u2 local_variable_table_length; 036// { u2 start_pc; 037// u2 length; 038// u2 name_index; 039// u2 descriptor_index; 040// u2 index; 041// } local_variable_table[local_variable_table_length]; 042// } 043 044//LocalVariableTypeTable_attribute { 045// u2 attribute_name_index; 046// u4 attribute_length; 047// u2 local_variable_type_table_length; 048// { 049// u2 start_pc; 050// u2 length; 051// u2 name_index; 052// u2 signature_index; 053// u2 index; 054// } localVariableTypeTable[local_variable_type_table_length]; 055// } 056// J5TODO: Needs some testing ! 057 058/** 059 * @since 6.0 060 */ 061public class LocalVariableTypeTable extends Attribute implements Iterable<LocalVariable> { 062 063 private static final LocalVariable[] EMPTY_ARRAY = {}; 064 065 private LocalVariable[] localVariableTypeTable; // variables 066 067 LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException { 068 this(nameIdx, len, (LocalVariable[]) null, cpool); 069 final int localVariableTypeTableLength = input.readUnsignedShort(); 070 localVariableTypeTable = new LocalVariable[localVariableTypeTableLength]; 071 for (int i = 0; i < localVariableTypeTableLength; i++) { 072 localVariableTypeTable[i] = new LocalVariable(input, cpool); 073 } 074 } 075 076 public LocalVariableTypeTable(final int nameIndex, final int length, final LocalVariable[] localVariableTypeTable, final ConstantPool constantPool) { 077 super(Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE, nameIndex, length, constantPool); 078 this.localVariableTypeTable = localVariableTypeTable != null ? localVariableTypeTable : LocalVariable.EMPTY_ARRAY; 079 Args.requireU2(this.localVariableTypeTable.length, "localVariableTypeTable.length"); 080 } 081 082 public LocalVariableTypeTable(final LocalVariableTypeTable c) { 083 this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), c.getConstantPool()); 084 } 085 086 @Override 087 public void accept(final Visitor v) { 088 v.visitLocalVariableTypeTable(this); 089 } 090 091 /** 092 * @return deep copy of this attribute 093 */ 094 @Override 095 public Attribute copy(final ConstantPool constantPool) { 096 final LocalVariableTypeTable c = (LocalVariableTypeTable) clone(); 097 c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length]; 098 Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy()); 099 c.setConstantPool(constantPool); 100 return c; 101 } 102 103 @Override 104 public final void dump(final DataOutputStream file) throws IOException { 105 super.dump(file); 106 file.writeShort(localVariableTypeTable.length); 107 for (final LocalVariable variable : localVariableTypeTable) { 108 variable.dump(file); 109 } 110 } 111 112 public final LocalVariable getLocalVariable(final int index) { 113 for (final LocalVariable variable : localVariableTypeTable) { 114 if (variable.getIndex() == index) { 115 return variable; 116 } 117 } 118 return null; 119 } 120 121 public final LocalVariable[] getLocalVariableTypeTable() { 122 return localVariableTypeTable; 123 } 124 125 public final int getTableLength() { 126 return localVariableTypeTable == null ? 0 : localVariableTypeTable.length; 127 } 128 129 @Override 130 public Iterator<LocalVariable> iterator() { 131 return Stream.of(localVariableTypeTable).iterator(); 132 } 133 134 public final void setLocalVariableTable(final LocalVariable[] localVariableTable) { 135 this.localVariableTypeTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY; 136 } 137 138 /** 139 * @return String representation. 140 */ 141 @Override 142 public final String toString() { 143 final StringBuilder buf = new StringBuilder(); 144 for (int i = 0; i < localVariableTypeTable.length; i++) { 145 buf.append(localVariableTypeTable[i].toStringShared(true)); 146 if (i < localVariableTypeTable.length - 1) { 147 buf.append('\n'); 148 } 149 } 150 return buf.toString(); 151 } 152}