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 */ 017package org.apache.commons.compress.harmony.unpack200.bytecode; 018 019import java.io.DataOutputStream; 020import java.io.IOException; 021import java.util.ArrayList; 022import java.util.List; 023 024import org.apache.commons.compress.harmony.pack200.Pack200Exception; 025 026/** 027 * Local variable type table. 028 */ 029public class LocalVariableTypeTableAttribute extends BCIRenumberedAttribute { 030 031 private final int local_variable_type_table_length; 032 private final int[] start_pcs; 033 private final int[] lengths; 034 private int[] name_indexes; 035 private int[] signature_indexes; 036 private final int[] indexes; 037 private final CPUTF8[] names; 038 private final CPUTF8[] signatures; 039 private int codeLength; 040 private static CPUTF8 attributeName; 041 042 public static void setAttributeName(final CPUTF8 cpUTF8Value) { 043 attributeName = cpUTF8Value; 044 } 045 046 public LocalVariableTypeTableAttribute(final int local_variable_type_table_length, final int[] start_pcs, 047 final int[] lengths, final CPUTF8[] names, final CPUTF8[] signatures, final int[] indexes) { 048 super(attributeName); 049 this.local_variable_type_table_length = local_variable_type_table_length; 050 this.start_pcs = start_pcs; 051 this.lengths = lengths; 052 this.names = names; 053 this.signatures = signatures; 054 this.indexes = indexes; 055 } 056 057 public void setCodeLength(final int length) { 058 codeLength = length; 059 } 060 061 @Override 062 protected int getLength() { 063 return 2 + (10 * local_variable_type_table_length); 064 } 065 066 @Override 067 protected void writeBody(final DataOutputStream dos) throws IOException { 068 dos.writeShort(local_variable_type_table_length); 069 for (int i = 0; i < local_variable_type_table_length; i++) { 070 dos.writeShort(start_pcs[i]); 071 dos.writeShort(lengths[i]); 072 dos.writeShort(name_indexes[i]); 073 dos.writeShort(signature_indexes[i]); 074 dos.writeShort(indexes[i]); 075 } 076 } 077 078 @Override 079 protected void resolve(final ClassConstantPool pool) { 080 super.resolve(pool); 081 name_indexes = new int[local_variable_type_table_length]; 082 signature_indexes = new int[local_variable_type_table_length]; 083 for (int i = 0; i < local_variable_type_table_length; i++) { 084 names[i].resolve(pool); 085 signatures[i].resolve(pool); 086 name_indexes[i] = pool.indexOf(names[i]); 087 signature_indexes[i] = pool.indexOf(signatures[i]); 088 } 089 } 090 091 @Override 092 protected ClassFileEntry[] getNestedClassFileEntries() { 093 final ArrayList nestedEntries = new ArrayList(); 094 nestedEntries.add(getAttributeName()); 095 for (int i = 0; i < local_variable_type_table_length; i++) { 096 nestedEntries.add(names[i]); 097 nestedEntries.add(signatures[i]); 098 } 099 final ClassFileEntry[] nestedEntryArray = new ClassFileEntry[nestedEntries.size()]; 100 nestedEntries.toArray(nestedEntryArray); 101 return nestedEntryArray; 102 } 103 104 @Override 105 protected int[] getStartPCs() { 106 return start_pcs; 107 } 108 109 /* 110 * (non-Javadoc) 111 * 112 * @see org.apache.commons.compress.harmony.unpack200.bytecode.BCIRenumberedAttribute#renumber(java.util.List) 113 */ 114 @Override 115 public void renumber(final List byteCodeOffsets) throws Pack200Exception { 116 // Remember the unrenumbered start_pcs, since that's used later 117 // to calculate end position. 118 final int[] unrenumbered_start_pcs = new int[start_pcs.length]; 119 System.arraycopy(start_pcs, 0, unrenumbered_start_pcs, 0, start_pcs.length); 120 121 // Next renumber start_pcs in place 122 super.renumber(byteCodeOffsets); 123 124 // lengths are BRANCH5 encoded, not BCI-encoded. 125 // In other words: 126 // start_pc is BCI5 start_pc 127 // end_pc is byteCodeOffset[(index of start_pc in byteCodeOffset) + 128 // (encoded length)] 129 // real length = end_pc - start_pc 130 // special case if end_pc is beyond end of bytecode array 131 132 final int maxSize = codeLength; 133 134 // Iterate through the lengths and update each in turn. 135 // This is done in place in the lengths array. 136 for (int index = 0; index < lengths.length; index++) { 137 final int start_pc = start_pcs[index]; 138 int revisedLength = -1; 139 final int encodedLength = lengths[index]; 140 141 // First get the index of the start_pc in the byteCodeOffsets 142 final int indexOfStartPC = unrenumbered_start_pcs[index]; 143 // Given the index of the start_pc, we can now add 144 // the encodedLength to it to get the stop index. 145 final int stopIndex = indexOfStartPC + encodedLength; 146 if (stopIndex < 0) { 147 throw new Pack200Exception("Error renumbering bytecode indexes"); 148 } 149 // Length can either be an index into the byte code offsets, or one 150 // beyond the 151 // end of the byte code offsets. Need to determine which this is. 152 if (stopIndex == byteCodeOffsets.size()) { 153 // Pointing to one past the end of the byte code array 154 revisedLength = maxSize - start_pc; 155 } else { 156 // We're indexed into the byte code array 157 final int stopValue = ((Integer) byteCodeOffsets.get(stopIndex)).intValue(); 158 revisedLength = stopValue - start_pc; 159 } 160 lengths[index] = revisedLength; 161 } 162 } 163 164 @Override 165 public String toString() { 166 return "LocalVariableTypeTable: " + +local_variable_type_table_length + " varaibles"; 167 } 168 169}