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 LocalVariable[] localVariableTypeTable; // variables 064 065 LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException { 066 this(nameIdx, len, (LocalVariable[]) null, cpool); 067 068 final int localVariableTypeTableLength = input.readUnsignedShort(); 069 localVariableTypeTable = new LocalVariable[localVariableTypeTableLength]; 070 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 098 c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length]; 099 Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy()); 100 c.setConstantPool(constantPool); 101 return c; 102 } 103 104 @Override 105 public final void dump(final DataOutputStream file) throws IOException { 106 super.dump(file); 107 file.writeShort(localVariableTypeTable.length); 108 for (final LocalVariable variable : localVariableTypeTable) { 109 variable.dump(file); 110 } 111 } 112 113 public final LocalVariable getLocalVariable(final int index) { 114 for (final LocalVariable variable : localVariableTypeTable) { 115 if (variable.getIndex() == index) { 116 return variable; 117 } 118 } 119 120 return null; 121 } 122 123 public final LocalVariable[] getLocalVariableTypeTable() { 124 return localVariableTypeTable; 125 } 126 127 public final int getTableLength() { 128 return localVariableTypeTable == null ? 0 : localVariableTypeTable.length; 129 } 130 131 @Override 132 public Iterator<LocalVariable> iterator() { 133 return Stream.of(localVariableTypeTable).iterator(); 134 } 135 136 public final void setLocalVariableTable(final LocalVariable[] localVariableTable) { 137 this.localVariableTypeTable = localVariableTable; 138 } 139 140 /** 141 * @return String representation. 142 */ 143 @Override 144 public final String toString() { 145 final StringBuilder buf = new StringBuilder(); 146 147 for (int i = 0; i < localVariableTypeTable.length; i++) { 148 buf.append(localVariableTypeTable[i].toStringShared(true)); 149 150 if (i < localVariableTypeTable.length - 1) { 151 buf.append('\n'); 152 } 153 } 154 155 return buf.toString(); 156 } 157}