1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * https://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package org.apache.bcel.verifier.statics; 20 21 import java.util.Hashtable; 22 23 import org.apache.bcel.generic.Type; 24 import org.apache.bcel.verifier.exc.LocalVariableInfoInconsistentException; 25 26 /** 27 * A utility class holding the information about the name and the type of a local variable in a given slot (== index). 28 * This information often changes in course of byte code offsets. 29 */ 30 public class LocalVariableInfo { 31 32 /** The types database. KEY: String representing the offset integer. */ 33 private final Hashtable<String, Type> types = new Hashtable<>(); 34 35 /** The names database. KEY: String representing the offset integer. */ 36 private final Hashtable<String, String> names = new Hashtable<>(); 37 38 /** 39 * Adds information about name and type for a given offset. 40 * 41 * @throws LocalVariableInfoInconsistentException if the new information conflicts with already gathered information. 42 */ 43 private void add(final int offset, final String name, final Type t) throws LocalVariableInfoInconsistentException { 44 if (getName(offset) != null && !getName(offset).equals(name)) { 45 throw new LocalVariableInfoInconsistentException( 46 "At bytecode offset '" + offset + "' a local variable has two different names: '" + getName(offset) + "' and '" + name + "'."); 47 } 48 if (getType(offset) != null && !getType(offset).equals(t)) { 49 throw new LocalVariableInfoInconsistentException( 50 "At bytecode offset '" + offset + "' a local variable has two different types: '" + getType(offset) + "' and '" + t + "'."); 51 } 52 setName(offset, name); 53 setType(offset, t); 54 } 55 56 /** 57 * Adds some information about this local variable (slot). 58 * 59 * @param name variable name 60 * @param startPc Range in which the variable is valid. 61 * @param length length of ... 62 * @param type variable type 63 * @throws LocalVariableInfoInconsistentException if the new information conflicts with already gathered information. 64 */ 65 public void add(final String name, final int startPc, final int length, final Type type) throws LocalVariableInfoInconsistentException { 66 for (int i = startPc; i <= startPc + length; i++) { // incl/incl-notation! 67 add(i, name, type); 68 } 69 } 70 71 /** 72 * Returns the name of the local variable that uses this local variable slot at the given bytecode offset. Care for 73 * legal bytecode offsets yourself, otherwise the return value might be wrong. May return 'null' if nothing is known 74 * about the type of this local variable slot at the given bytecode offset. 75 * 76 * @param offset bytecode offset. 77 * @return the name of the local variable that uses this local variable slot at the given bytecode offset. 78 */ 79 public String getName(final int offset) { 80 return names.get(Integer.toString(offset)); 81 } 82 83 /** 84 * Returns the type of the local variable that uses this local variable slot at the given bytecode offset. Care for 85 * legal bytecode offsets yourself, otherwise the return value might be wrong. May return 'null' if nothing is known 86 * about the type of this local variable slot at the given bytecode offset. 87 * 88 * @param offset bytecode offset. 89 * @return the type of the local variable that uses this local variable slot at the given bytecode offset. 90 */ 91 public Type getType(final int offset) { 92 return types.get(Integer.toString(offset)); 93 } 94 95 /** 96 * Adds a name of a local variable and a certain slot to our 'names' (Hashtable) database. 97 */ 98 private void setName(final int offset, final String name) { 99 names.put(Integer.toString(offset), name); 100 } 101 102 /** 103 * Adds a type of a local variable and a certain slot to our 'types' (Hashtable) database. 104 */ 105 private void setType(final int offset, final Type t) { 106 types.put(Integer.toString(offset), t); 107 } 108 }