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