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 }