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