View Javadoc
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: LocalVariableInfo.html 992795 2016-07-14 11:53:52Z britter $
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       */
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       */
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       */
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       */
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       */
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       */
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 }