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  import org.apache.bcel.generic.Type;
23  import org.apache.bcel.verifier.exc.LocalVariableInfoInconsistentException;
24  
25  /**
26   * A utility class holding the information about
27   * the name and the type of a local variable in
28   * a given slot (== index). This information
29   * often changes in course of byte code offsets.
30   *
31   * @version $Id: LocalVariableInfo.html 898356 2014-02-18 05:44:40Z ggregory $
32   * @author Enver Haase
33   */
34  public class LocalVariableInfo{
35  
36  	/** The types database. KEY: String representing the offset integer. */
37  	private Hashtable<String, Type> types = new Hashtable<String, Type>();
38  	/** The names database. KEY: String representing the offset integer. */
39  	private Hashtable<String, String> names = new Hashtable<String, String>();
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(int offset, 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(int offset, 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(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(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(String name, int startpc, int length, 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(int offset, String name, Type t) throws LocalVariableInfoInconsistentException{
95  		if (getName(offset) != null){
96  			if (! getName(offset).equals(name)){
97  				throw new LocalVariableInfoInconsistentException("At bytecode offset '"+offset+"' a local variable has two different names: '"+getName(offset)+"' and '"+name+"'.");
98  			}
99  		}
100 		if (getType(offset) != null){
101 			if (! getType(offset).equals(t)){
102 				throw new LocalVariableInfoInconsistentException("At bytecode offset '"+offset+"' a local variable has two different types: '"+getType(offset)+"' and '"+t+"'.");
103 			}
104 		}
105 		setName(offset, name);
106 		setType(offset, t);
107 	}
108 }