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 */ 18 package org.apache.bcel.verifier.statics; 19 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 28 * the name and the type of a local variable in 29 * a given slot (== index). This information 30 * often changes in course of byte code offsets. 31 * 32 * @version $Id$ 33 */ 34 public class LocalVariableInfo{ 35 36 /** The types database. KEY: String representing the offset integer. */ 37 private final Hashtable<String, Type> types = new Hashtable<>(); 38 /** The names database. KEY: String representing the offset integer. */ 39 private final Hashtable<String, String> names = new Hashtable<>(); 40 41 /** 42 * Adds a name of a local variable and a certain slot to our 'names' 43 * (Hashtable) database. 44 */ setName(final int offset, final String name)45 private void setName(final int offset, final String name) { 46 names.put(Integer.toString(offset), name); 47 } 48 /** 49 * Adds a type of a local variable and a certain slot to our 'types' 50 * (Hashtable) database. 51 */ setType(final int offset, final Type t)52 private void setType(final int offset, final Type t) { 53 types.put(Integer.toString(offset), t); 54 } 55 56 /** 57 * Returns the type of the local variable that uses this local 58 * variable slot at the given bytecode offset. 59 * Care for legal bytecode offsets yourself, otherwise the return value 60 * might be wrong. 61 * May return 'null' if nothing is known about the type of this local 62 * variable slot at the given bytecode offset. 63 */ getType(final int offset)64 public Type getType(final int offset) { 65 return types.get(Integer.toString(offset)); 66 } 67 /** 68 * Returns the name of the local variable that uses this local 69 * variable slot at the given bytecode offset. 70 * Care for legal bytecode offsets yourself, otherwise the return value 71 * might be wrong. 72 * May return 'null' if nothing is known about the type of this local 73 * variable slot at the given bytecode offset. 74 */ getName(final int offset)75 public String getName(final int offset) { 76 return names.get(Integer.toString(offset)); 77 } 78 /** 79 * Adds some information about this local variable (slot). 80 * @throws LocalVariableInfoInconsistentException if the new information conflicts 81 * with already gathered information. 82 */ add(final String name, final int startpc, final int length, final Type t)83 public void add(final String name, final int startpc, final int length, final Type t) throws LocalVariableInfoInconsistentException{ 84 for (int i=startpc; i<=startpc+length; i++) { // incl/incl-notation! 85 add(i,name,t); 86 } 87 } 88 89 /** 90 * Adds information about name and type for a given offset. 91 * @throws LocalVariableInfoInconsistentException if the new information conflicts 92 * with already gathered information. 93 */ add(final int offset, final String name, final Type t)94 private void add(final int offset, final String name, final Type t) throws LocalVariableInfoInconsistentException{ 95 if (getName(offset) != null) { 96 if (! getName(offset).equals(name)) { 97 throw new LocalVariableInfoInconsistentException("At bytecode offset '"+offset+ 98 "' a local variable has two different names: '"+getName(offset)+"' and '"+name+"'."); 99 } 100 } 101 if (getType(offset) != null) { 102 if (! getType(offset).equals(t)) { 103 throw new LocalVariableInfoInconsistentException("At bytecode offset '"+offset+ 104 "' a local variable has two different types: '"+getType(offset)+"' and '"+t+"'."); 105 } 106 } 107 setName(offset, name); 108 setType(offset, t); 109 } 110 } 111