1 cananian 1.1 // MethodGenerator.java, created Fri Jul 11 02:53:45 2003 by cananian 2 cananian 1.1 // Copyright (C) 2003 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1 package harpoon.Analysis.Transactions; 5 cananian 1.1 6 cananian 1.1 import harpoon.ClassFile.HClass; 7 cananian 1.1 import harpoon.ClassFile.HClassMutator; 8 cananian 1.1 import harpoon.ClassFile.HMethod; 9 cananian 1.1 10 cananian 1.1 import java.lang.reflect.Modifier; 11 cananian 1.2 import java.util.Collections; 12 cananian 1.1 import java.util.HashMap; 13 cananian 1.1 import java.util.Map; 14 cananian 1.2 import java.util.Set; 15 cananian 1.1 /** 16 cananian 1.1 * A <code>MethodGenerator</code> creates methods with base names and 17 cananian 1.1 * parameters/return types you specify. 18 cananian 1.1 * 19 cananian 1.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 20 cananian 1.2 * @version $Id: MethodGenerator.java,v 1.2 2003/07/21 21:21:49 cananian Exp $ 21 cananian 1.1 */ 22 cananian 1.1 class MethodGenerator { 23 cananian 1.1 private final HClassMutator classMutator; 24 cananian 1.1 private static final String separator = "_"; 25 cananian 1.1 26 cananian 1.1 /** Creates a <code>MethodGenerator</code> which creates methods 27 cananian 1.1 * in the given <code>HClass</code>. */ 28 cananian 1.1 public MethodGenerator(HClass baseClass) { 29 cananian 1.1 this.classMutator = baseClass.getMutator(); 30 cananian 1.1 } 31 cananian 1.2 32 cananian 1.1 /** Return the 'name' originally given to lookupMethod (which will 33 cananian 1.1 * differ from the name reported by the method via getName()). */ 34 cananian 1.2 public String baseName(HMethod hm) { 35 cananian 1.2 assert generatedMethodSet.contains(hm); 36 cananian 1.2 return descriptors.get(hm).namePrefix; 37 cananian 1.1 } 38 cananian 1.1 public HMethod lookupMethod(String name, HClass[] argTypes, HClass retType) 39 cananian 1.1 { 40 cananian 1.1 MethodDescriptor md = new MethodDescriptor(name, argTypes, retType); 41 cananian 1.1 HMethod hm = methods.get(md); 42 cananian 1.1 if (hm!=null) return hm; 43 cananian 1.1 // add counter to name to guarantee uniqueness. 44 cananian 1.1 hm = classMutator.addDeclaredMethod 45 cananian 1.1 (name+separator+(counter++), argTypes, retType); 46 cananian 1.2 hm.getMutator().addModifiers(Modifier.FINAL | //Modifier.NATIVE | 47 cananian 1.1 Modifier.STATIC | Modifier.PUBLIC); 48 cananian 1.1 methods.put(md, hm); 49 cananian 1.2 descriptors.put(hm, md); 50 cananian 1.1 return hm; 51 cananian 1.1 } 52 cananian 1.1 private final Map<MethodDescriptor,HMethod> methods = 53 cananian 1.1 new HashMap<MethodDescriptor,HMethod>(); 54 cananian 1.2 private final Map<HMethod,MethodDescriptor> descriptors = 55 cananian 1.2 new HashMap<HMethod,MethodDescriptor>(); 56 cananian 1.1 int counter = 0; 57 cananian 1.2 58 cananian 1.2 /** The <code>Set</code> of all <code>HMethod</code>s generated 59 cananian 1.2 * by this <code>MethodGenerator</code>. */ 60 cananian 1.2 public final Set<HMethod> generatedMethodSet = 61 cananian 1.2 Collections.unmodifiableSet(descriptors.keySet()); 62 cananian 1.1 63 cananian 1.1 /** The <code>MethodDescriptor</code> is a handy tuple type to serve 64 cananian 1.1 * as keys in the hashtable. */ 65 cananian 1.1 static class MethodDescriptor { 66 cananian 1.1 final String namePrefix; 67 cananian 1.1 final HClass[] argTypes; 68 cananian 1.1 final HClass retType; 69 cananian 1.1 MethodDescriptor(String namePrefix, HClass[] argTypes, HClass retType){ 70 cananian 1.1 this.namePrefix = namePrefix; 71 cananian 1.1 this.argTypes = argTypes; 72 cananian 1.1 this.retType = retType; 73 cananian 1.1 } 74 cananian 1.1 public int hashCode() { 75 cananian 1.1 int hash = namePrefix.hashCode() + retType.hashCode(); 76 cananian 1.1 hash += argTypes.length; 77 cananian 1.1 for(int i=0; i<argTypes.length; i++) 78 cananian 1.1 hash += argTypes[i].hashCode(); 79 cananian 1.1 return hash; 80 cananian 1.1 } 81 cananian 1.1 public boolean equals(Object o) { 82 cananian 1.1 if (this==o) return true; 83 cananian 1.1 if (!(o instanceof MethodDescriptor)) return false; 84 cananian 1.1 MethodDescriptor md = (MethodDescriptor) o; 85 cananian 1.1 if (!this.namePrefix.equals(md.namePrefix)) return false; 86 cananian 1.1 if (!this.retType.equals(md.retType)) return false; 87 cananian 1.1 if (this.argTypes.length != md.argTypes.length) return false; 88 cananian 1.1 for (int i=0; i<this.argTypes.length; i++) 89 cananian 1.1 if (!this.argTypes[i].equals(md.argTypes[i])) return false; 90 cananian 1.1 return true; // exactly the same. 91 cananian 1.1 } 92 cananian 1.1 } 93 cananian 1.1 }