00001 package edu.ksu.cis.bandera.bofa; 00002 00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00004 * Bandera, a Java(TM) analysis and transformation toolkit * 00005 * Copyright (C) 1998, 1999 Shawn Laubach (laubach@acm.org) * 00006 * All rights reserved. * 00007 * * 00008 * This work was done as a project in the SAnToS Laboratory, * 00009 * Department of Computing and Information Sciences, Kansas State * 00010 * University, USA (http://www.cis.ksu.edu/santos). * 00011 * It is understood that any modification not identified as such is * 00012 * not covered by the preceding statement. * 00013 * * 00014 * This work is free software; you can redistribute it and/or * 00015 * modify it under the terms of the GNU Library General Public * 00016 * License as published by the Free Software Foundation; either * 00017 * version 2 of the License, or (at your option) any later version. * 00018 * * 00019 * This work is distributed in the hope that it will be useful, * 00020 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00022 * Library General Public License for more details. * 00023 * * 00024 * You should have received a copy of the GNU Library General Public * 00025 * License along with this toolkit; if not, write to the * 00026 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * 00027 * Boston, MA 02111-1307, USA. * 00028 * * 00029 * Java is a trademark of Sun Microsystems, Inc. * 00030 * * 00031 * To submit a bug report, send a comment, or get the latest news on * 00032 * this project and other SAnToS projects, please visit the web-site * 00033 * http://www.cis.ksu.edu/santos * 00034 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00035 00036 import ca.mcgill.sable.soot.*; 00037 import ca.mcgill.sable.util.*; 00038 00039 /* 00040 * ClassTokenArray.java 00041 * $Id: ClassTokenArray.java,v 1.1.1.1 2002/01/24 03:42:07 pserver Exp $ 00042 */ 00043 00044 /** 00045 * This class represents the class token for array types in the analysis. In 00046 * java array types are represented as classes. 00047 * 00048 * @author <A HREF="http://www.cis.ksu.edu/~hatcliff">John Hatcliff</A> 00049 * @author 00050 * <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a> 00051 * 00052 * @version $Name: $($Revision: 1.1.1.1 $) 00053 */ 00054 public class ClassTokenArray implements ClassToken 00055 { 00056 /** 00057 * Maps an array type to a class token,<code>ClassToken</code>. 00058 * 00059 * An integer array of 3 dimension is an array type. 00060 */ 00061 private static Map allocatedTokens = new HashMap(); 00062 00063 /** 00064 * The ArrayType object associated with this class token object. 00065 */ 00066 ArrayType arrayType; 00067 00068 /** 00069 * Creates a new object. 00070 * 00071 * @param arrayType the array type associated with this class token. 00072 */ 00073 private ClassTokenArray(ArrayType arrayType) 00074 { 00075 this.arrayType = arrayType; 00076 } 00077 /** 00078 * Extracts the component type of the given array type. 00079 * 00080 * @param arrayType the array type whose component type is requested. 00081 * @return the component type of the given array type. 00082 */ 00083 public static Type arrayTypeToComponentType(ArrayType arrayType) 00084 { 00085 if (arrayType.numDimensions == 1) { 00086 return arrayType.baseType; 00087 } else { 00088 return ArrayType.v(arrayType.baseType, 00089 arrayType.numDimensions - 1); 00090 } 00091 } 00092 /** 00093 * Constructs a new array type in which the component type is of the given 00094 * type. 00095 * 00096 * @param componentType the component type of the requested array type. 00097 * @return the new array type with the given component type. 00098 */ 00099 public static ArrayType componentToArrayType(Type componentType) 00100 { 00101 if (componentType instanceof BaseType) { 00102 return ArrayType.v((BaseType) componentType, 1); 00103 } else 00104 if (componentType instanceof ArrayType) { 00105 return ArrayType.v(((ArrayType) componentType).baseType, 00106 ((ArrayType) componentType).numDimensions + 00107 1); 00108 } else 00109 throw new RuntimeException("Invalid type"); 00110 } 00111 /** 00112 * Returns the ArrayType associated with this class token. 00113 * 00114 * @return a soot object representing the array type associated with this 00115 * class token. 00116 */ 00117 public ArrayType getArrayType() 00118 { 00119 return arrayType; 00120 } 00121 /** 00122 * Provides the class token associated with the given array type. 00123 * 00124 * In this method, array types are tested for logical equality rather 00125 * than object equality. It is the case that there may be more than one 00126 * SootClass object pertaining to equivalent array types. Hence, the name 00127 * getCanonicalArrayTypeInstance. 00128 * 00129 * @param arrayType the array type which needs to be checked if registered 00130 * @return the class token associated with the array type, if any, else null. 00131 */ 00132 private static ArrayType getCanonicalArrayTypeInstance(ArrayType arrayType) 00133 { 00134 /** 00135 * Iterates over stored array types in allocatedTokens map to see if we 00136 * have already allocated a ClassTokenArray for a logically 00137 * equivalent array type. If we have, return that array type 00138 * instance. If we have * not, return null. 00139 */ 00140 ArrayType storedArrayType; 00141 for (Iterator i = allocatedTokens.keySet().iterator(); i.hasNext();) 00142 { 00143 storedArrayType = (ArrayType) i.next(); 00144 if (storedArrayType.equals(arrayType)) { 00145 return storedArrayType; 00146 } 00147 } 00148 return null; 00149 } 00150 /** 00151 * Provides the class token associated with the given array type. 00152 * 00153 * @param arrayType the array type for which the class token is requested. 00154 * @return the class token associated with the array type. 00155 */ 00156 public static ClassTokenArray select(ArrayType arrayType) 00157 { 00158 ClassTokenArray classTokenArray; 00159 00160 /* 00161 * Currently, Soot allows multiple array type instances to describe the 00162 * same array type. We want a single ClassTokenArray instance for each 00163 * distinct logical array type. in simple words, Soot associates a 00164 * unique SootClass object with each 3 dimensional array of type A 00165 * whereas we require one SootClass object to be associated with all 3 00166 * dimensional arrays of type A. Therefore, before allocating a new 00167 * ClassTokenArray instance, we want to check to see if a 00168 * ClassTokenArray instance has already been allocated for a given 00169 * logical type. 00170 */ 00171 00172 /* 00173 * First, check to see if the the given array type is already stored in 00174 * the table. 00175 */ 00176 if (allocatedTokens.containsKey(arrayType)) { 00177 classTokenArray = (ClassTokenArray) allocatedTokens.get(arrayType); 00178 } else { 00179 /* 00180 * Check if a logically equivalent array type is stored in the 00181 * table. If so, use that or create a new one. 00182 */ 00183 ArrayType canonicalArrayType = 00184 getCanonicalArrayTypeInstance(arrayType); 00185 00186 if (canonicalArrayType != null) { 00187 // return the classToken associated with the array type 00188 classTokenArray = (ClassTokenArray) 00189 allocatedTokens.get(canonicalArrayType); 00190 } else { 00191 // there is no logically equivalent stored array type, so 00192 // create a new class token for it, and the current array type 00193 // becomes the canonical representation. 00194 classTokenArray = new ClassTokenArray(arrayType); 00195 allocatedTokens.put(arrayType,classTokenArray); 00196 } 00197 } 00198 return classTokenArray; 00199 } 00200 }