1 cananian 1.1.4.1 // HClassProxy.java, created Tue Jan 11 07:39:47 2000 by cananian 2 cananian 1.1.4.3 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.4.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.4.1 package harpoon.ClassFile; 5 cananian 1.1.4.1 6 cananian 1.1.4.1 import harpoon.Util.ArrayFactory; 7 cananian 1.5 import net.cscott.jutil.ReferenceUnique; 8 cananian 1.5 import net.cscott.jutil.UniqueVector; 9 cananian 1.1.4.1 import harpoon.Util.Util; 10 cananian 1.1.4.1 11 cananian 1.1.4.1 import java.lang.reflect.Modifier; 12 cananian 1.1.4.4 import java.io.Serializable; 13 cananian 1.1.4.1 /** 14 cananian 1.1.4.1 * <code>HClassProxy</code> serves as a proxy class for 15 cananian 1.1.4.1 * <code>HClass</code> objects, allowing them to be swapped out & 16 cananian 1.1.4.1 * "redefined" after creation. 17 cananian 1.1.4.1 * 18 cananian 1.1.4.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 19 cananian 1.5 * @version $Id: HClassProxy.java,v 1.5 2004/02/08 01:58:03 cananian Exp $ 20 cananian 1.1.4.1 */ 21 cananian 1.1.4.4 class HClassProxy extends HClass implements HClassMutator, Serializable { 22 cananian 1.1.4.1 Relinker relinker; 23 cananian 1.1.4.1 HClass proxy; 24 cananian 1.1.4.1 HClassMutator proxyMutator; 25 cananian 1.1.4.1 // this boolean indicates whether the proxied class is from 26 cananian 1.1.4.1 // the same linker as this HClassProxy, which only happens 27 cananian 1.1.4.1 // when our linker create new HClassSyns 28 cananian 1.1.4.1 boolean sameLinker; 29 cananian 1.1.4.1 30 cananian 1.1.4.1 HClassProxy(Relinker l, HClass proxy) { 31 cananian 1.1.4.1 super(l); 32 cananian 1.1.4.1 this.relinker = l; 33 cananian 1.1.4.1 relink(proxy); 34 cananian 1.1.4.1 } 35 cananian 1.1.4.1 void relink(HClass newproxy) { 36 cananian 1.3.2.1 assert newproxy!=null; 37 cananian 1.3.2.1 assert !(newproxy instanceof HClassProxy && 38 cananian 1.3.2.1 ((HClassProxy)newproxy).relinker==relinker) : "should never proxy to a proxy of this same relinker."; 39 cananian 1.1.4.1 // first update all the fields and methods hanging around. 40 cananian 1.1.4.1 if (proxy!=null) { 41 cananian 1.1.4.1 HField[] hf = proxy.getDeclaredFields(); 42 cananian 1.1.4.1 for (int i=0; i<hf.length; i++) 43 cananian 1.1.4.1 try { 44 cananian 1.1.4.1 HFieldProxy hfp = (HFieldProxy) relinker.memberMap.get(hf[i]); 45 cananian 1.1.4.1 if (hfp==null) continue; 46 cananian 1.1.4.1 hfp.flushMemberMap(); hfp.relink(null); 47 cananian 1.1.4.1 HField nhf = newproxy.getDeclaredField(hf[i].getName()); 48 cananian 1.1.4.1 if (!nhf.getDescriptor().equals(hf[i].getDescriptor())) continue; 49 cananian 1.1.4.1 hfp.relink(nhf); hfp.updateMemberMap(); 50 cananian 1.1.4.1 } catch (NoSuchFieldError e) { /* skip */ } 51 cananian 1.1.4.1 HMethod[] hm = proxy.getDeclaredMethods(); 52 cananian 1.1.4.1 for (int i=0; i<hm.length; i++) 53 cananian 1.1.4.1 try { 54 cananian 1.1.4.1 HMethodProxy hmp = (HMethodProxy) relinker.memberMap.get(hm[i]); 55 cananian 1.1.4.1 if (hmp==null) continue; 56 cananian 1.1.4.1 hmp.flushMemberMap(); hmp.relink(null); 57 cananian 1.1.4.1 HMethod nhm = newproxy.getDeclaredMethod(hm[i].getName(), 58 cananian 1.1.4.1 hm[i].getDescriptor()); 59 cananian 1.1.4.1 hmp.relink(nhm); hmp.updateMemberMap(); 60 cananian 1.1.4.1 } catch (NoSuchMethodError e) { /* skip */ } 61 cananian 1.1.4.1 } 62 cananian 1.1.4.1 // okay, now that the members are updated, let's update this guy. 63 cananian 1.1.4.1 this.proxy = newproxy; 64 cananian 1.1.4.1 this.proxyMutator = newproxy.getMutator(); 65 cananian 1.1.4.1 this.sameLinker = (relinker == newproxy.getLinker()); 66 cananian 1.1.4.1 } 67 cananian 1.1.4.1 68 cananian 1.1.4.1 /** 69 cananian 1.1.4.1 * Returns a mutator for this <code>HClass</code>, or <code>null</code> 70 cananian 1.1.4.1 * if this object is immutable. 71 cananian 1.1.4.1 */ 72 cananian 1.1.4.1 public HClassMutator getMutator() { 73 cananian 1.1.4.1 if (proxyMutator==null) { 74 cananian 1.1.4.7 relink(isArray() 75 cananian 1.1.4.7 ? (HClass) new HClassArraySyn(relinker, 76 cananian 1.1.4.7 ((HClassArray)proxy).baseType, 77 cananian 1.1.4.7 ((HClassArray)proxy).dims) 78 cananian 1.1.4.7 : (HClass) new HClassSyn(relinker, proxy.getName(), this)); 79 cananian 1.1.4.1 proxy.hasBeenModified = false; // exact copy of proxy. 80 cananian 1.1.4.1 } 81 cananian 1.1.4.1 return (proxyMutator==null) ? null : this; 82 cananian 1.1.4.1 } 83 cananian 1.1.4.1 84 cananian 1.1.4.1 // the following methods need no special handling: 85 cananian 1.1.4.1 public boolean hasBeenModified() { return proxy.hasBeenModified(); } 86 cananian 1.1.4.1 public String getName() { return proxy.getName(); } 87 cananian 1.1.4.1 public String getPackage() { return proxy.getPackage(); } 88 cananian 1.1.4.1 public String getDescriptor() { return proxy.getDescriptor(); } 89 cananian 1.1.4.1 public String getSourceFile() { return proxy.getSourceFile(); } 90 cananian 1.1.4.1 public int getModifiers() { return proxy.getModifiers(); } 91 cananian 1.1.4.1 public boolean isArray() { return proxy.isArray(); } 92 cananian 1.1.4.1 public boolean isInterface() { return proxy.isInterface(); } 93 cananian 1.1.4.1 public boolean isPrimitive() { return proxy.isPrimitive(); } 94 cananian 1.1.4.1 95 cananian 1.1.4.1 // the following methods require use to unwrap the parameters and 96 cananian 1.1.4.1 // wrap up the return values. 97 cananian 1.1.4.1 public HField getDeclaredField(String name) throws NoSuchFieldError { 98 cananian 1.1.4.1 return wrap(proxy.getDeclaredField(name)); 99 cananian 1.1.4.1 } 100 cananian 1.1.4.1 public HField[] getDeclaredFields() { 101 cananian 1.1.4.1 return wrap(proxy.getDeclaredFields()); 102 cananian 1.1.4.1 } 103 cananian 1.1.4.1 public HMethod getDeclaredMethod(String name, HClass parameterTypes[]) 104 cananian 1.1.4.1 throws NoSuchMethodError { 105 cananian 1.1.4.1 return wrap(proxy.getDeclaredMethod(name, unwrap(parameterTypes))); 106 cananian 1.1.4.1 } 107 cananian 1.1.4.1 public HMethod getDeclaredMethod(String name, String descriptor) 108 cananian 1.1.4.1 throws NoSuchMethodError { 109 cananian 1.1.4.1 return wrap(proxy.getDeclaredMethod(name, descriptor)); 110 cananian 1.1.4.1 } 111 cananian 1.1.4.1 public HMethod[] getDeclaredMethods() { 112 cananian 1.1.4.1 return wrap(proxy.getDeclaredMethods()); 113 cananian 1.1.4.1 } 114 cananian 1.1.4.1 public HConstructor getConstructor(HClass parameterTypes[]) 115 cananian 1.1.4.1 throws NoSuchMethodError { 116 cananian 1.1.4.1 return wrap(proxy.getConstructor(unwrap(parameterTypes))); 117 cananian 1.1.4.1 } 118 cananian 1.1.4.1 public HConstructor[] getConstructors() { 119 cananian 1.1.4.1 return wrap(proxy.getConstructors()); 120 cananian 1.1.4.1 } 121 cananian 1.1.4.1 public HInitializer getClassInitializer() { 122 cananian 1.1.4.1 return wrap(proxy.getClassInitializer()); 123 cananian 1.1.4.1 } 124 cananian 1.1.4.1 public HClass getSuperclass() { 125 cananian 1.1.4.1 return wrap(proxy.getSuperclass()); 126 cananian 1.1.4.1 } 127 cananian 1.1.4.1 public HClass[] getInterfaces() { 128 cananian 1.1.4.1 return wrap(proxy.getInterfaces()); 129 cananian 1.1.4.7 } 130 cananian 1.1.4.7 public HClass getComponentType() { 131 cananian 1.1.4.7 return wrap(proxy.getComponentType()); 132 cananian 1.1.4.8 } 133 cananian 1.1.4.8 public boolean equals(Object o) { 134 cananian 1.1.4.8 return (o instanceof HClass && 135 cananian 1.1.4.8 ((HClass)o).getDescriptor().equals(getDescriptor())); 136 cananian 1.1.4.1 } 137 cananian 1.1.4.1 // HClassMutator interface 138 cananian 1.1.4.1 public HField addDeclaredField(String name, HClass type) 139 cananian 1.1.4.1 throws DuplicateMemberException { 140 cananian 1.1.4.1 return wrap(proxyMutator.addDeclaredField(name, unwrap(type))); 141 cananian 1.1.4.1 } 142 cananian 1.1.4.1 public HField addDeclaredField(String name, String descriptor) 143 cananian 1.1.4.1 throws DuplicateMemberException { 144 cananian 1.1.4.1 return wrap(proxyMutator.addDeclaredField(name, descriptor)); 145 cananian 1.1.4.1 } 146 cananian 1.1.4.1 public HField addDeclaredField(String name, HField template) 147 cananian 1.1.4.1 throws DuplicateMemberException { 148 cananian 1.1.4.1 return wrap(proxyMutator.addDeclaredField(name, template)); 149 cananian 1.1.4.1 } 150 cananian 1.1.4.1 public void removeDeclaredField(HField f) throws NoSuchMemberException { 151 cananian 1.1.4.1 HFieldProxy fp = (HFieldProxy) f; 152 cananian 1.1.4.1 fp.flushMemberMap(); 153 cananian 1.1.4.1 proxyMutator.removeDeclaredField(fp.proxy); 154 cananian 1.1.4.1 } 155 cananian 1.1.4.1 public HInitializer addClassInitializer() throws DuplicateMemberException { 156 cananian 1.1.4.1 return wrap(proxyMutator.addClassInitializer()); 157 cananian 1.1.4.1 } 158 cananian 1.1.4.1 public void removeClassInitializer(HInitializer m) 159 cananian 1.1.4.1 throws NoSuchMemberException { 160 cananian 1.1.4.1 HInitializerProxy ip = (HInitializerProxy) m; 161 cananian 1.1.4.1 ip.flushMemberMap(); 162 cananian 1.1.4.1 proxyMutator.removeClassInitializer((HInitializer)ip.proxy); 163 cananian 1.1.4.1 } 164 cananian 1.1.4.1 public HConstructor addConstructor(String descriptor) 165 cananian 1.1.4.1 throws DuplicateMemberException { 166 cananian 1.1.4.1 return wrap(proxyMutator.addConstructor(descriptor)); 167 cananian 1.1.4.1 } 168 cananian 1.1.4.1 public HConstructor addConstructor(HClass[] paramTypes) 169 cananian 1.1.4.1 throws DuplicateMemberException { 170 cananian 1.1.4.1 return wrap(proxyMutator.addConstructor(unwrap(paramTypes))); 171 cananian 1.1.4.1 } 172 cananian 1.1.4.1 public HConstructor addConstructor(HConstructor template) 173 cananian 1.1.4.1 throws DuplicateMemberException { 174 cananian 1.1.4.1 return wrap(proxyMutator.addConstructor(template)); 175 cananian 1.1.4.1 } 176 cananian 1.1.4.1 public void removeConstructor(HConstructor c) throws NoSuchMemberException { 177 cananian 1.1.4.1 HConstructorProxy cp = (HConstructorProxy) c; 178 cananian 1.1.4.1 cp.flushMemberMap(); 179 cananian 1.1.4.1 proxyMutator.removeConstructor((HConstructor)cp.proxy); 180 cananian 1.1.4.1 } 181 cananian 1.1.4.1 public HMethod addDeclaredMethod(String name, String descriptor) 182 cananian 1.1.4.1 throws DuplicateMemberException { 183 cananian 1.1.4.1 return wrap(proxyMutator.addDeclaredMethod(name, descriptor)); 184 cananian 1.1.4.1 } 185 cananian 1.1.4.1 public HMethod addDeclaredMethod(String name, HClass[] paramTypes, 186 cananian 1.1.4.1 HClass returnType) 187 cananian 1.1.4.1 throws DuplicateMemberException { 188 cananian 1.1.4.1 return wrap(proxyMutator.addDeclaredMethod(name, unwrap(paramTypes), 189 cananian 1.1.4.1 unwrap(returnType))); 190 cananian 1.1.4.1 } 191 cananian 1.1.4.1 public HMethod addDeclaredMethod(String name, HMethod template) 192 cananian 1.1.4.1 throws DuplicateMemberException { 193 cananian 1.1.4.1 return wrap(proxyMutator.addDeclaredMethod(name, template)); 194 cananian 1.1.4.1 } 195 cananian 1.1.4.1 public void removeDeclaredMethod(HMethod m) throws NoSuchMemberException { 196 cananian 1.1.4.1 HMethodProxy mp = (HMethodProxy) m; 197 cananian 1.1.4.1 mp.flushMemberMap(); 198 cananian 1.1.4.1 proxyMutator.removeDeclaredMethod(mp.proxy); 199 cananian 1.1.4.1 } 200 cananian 1.1.4.1 public void addInterface(HClass in) { 201 cananian 1.1.4.1 proxyMutator.addInterface(unwrap(in)); 202 cananian 1.1.4.1 } 203 cananian 1.1.4.1 public void removeInterface(HClass in) throws NoSuchClassException { 204 cananian 1.1.4.1 proxyMutator.removeInterface(unwrap(in)); 205 cananian 1.1.4.1 } 206 cananian 1.1.4.1 public void removeAllInterfaces() { proxyMutator.removeAllInterfaces(); } 207 cananian 1.1.4.1 public void addModifiers(int m) { proxyMutator.addModifiers(m); } 208 cananian 1.1.4.1 public void setModifiers(int m) { proxyMutator.setModifiers(m); } 209 cananian 1.1.4.1 public void removeModifiers(int m) { proxyMutator.removeModifiers(m); } 210 cananian 1.1.4.1 public void setSuperclass(HClass sc) { 211 cananian 1.1.4.1 proxyMutator.setSuperclass(unwrap(sc)); 212 cananian 1.1.4.1 } 213 cananian 1.1.4.1 public void setSourceFile(String sourcefilename) { 214 cananian 1.1.4.1 proxyMutator.setSourceFile(sourcefilename); 215 cananian 1.1.4.4 } 216 cananian 1.1.4.4 217 cananian 1.1.4.4 // Serializable interface. 218 cananian 1.1.4.4 // we have to work around the fact that the base HClass is not Serializable. 219 cananian 1.1.4.4 public Object writeReplace() { return new HClassProxyStub(this); } 220 cananian 1.1.4.4 private static final class HClassProxyStub implements java.io.Serializable { 221 cananian 1.1.4.4 private Relinker relinker; 222 cananian 1.1.4.4 private HClass proxy; 223 cananian 1.1.4.4 HClassProxyStub(HClassProxy hcp) { 224 cananian 1.1.4.4 this.relinker = hcp.relinker; 225 cananian 1.1.4.4 this.proxy = hcp.proxy; 226 cananian 1.1.4.4 } 227 cananian 1.1.4.4 public Object readResolve() { 228 cananian 1.1.4.5 // leverage relinker during reconstruct. this makes sure all our 229 cananian 1.1.4.5 // mappings are consistent with the descCache. 230 cananian 1.1.4.6 return relinker.load(proxy.getDescriptor(), proxy); 231 cananian 1.1.4.4 } 232 cananian 1.1.4.1 } 233 cananian 1.1.4.1 234 cananian 1.1.4.1 // wrap/unwrap methods. 235 cananian 1.1.4.1 private HClass wrap(HClass hc) { 236 cananian 1.1.4.5 //if (sameLinker && hc != proxy) return hc; else return relinker.wrap(hc); 237 cananian 1.1.4.5 return relinker.wrap(hc); // it can never hurt to wrap the class. 238 cananian 1.1.4.1 } 239 cananian 1.1.4.1 private HClass unwrap(HClass hc) { 240 cananian 1.1.4.5 if (sameLinker) return hc; else return relinker.unwrap(hc); 241 cananian 1.1.4.1 } 242 cananian 1.1.4.1 private HField wrap(HField hf) { return relinker.wrap(hf); } 243 cananian 1.1.4.1 private HMethod wrap(HMethod hm) { return relinker.wrap(hm); } 244 cananian 1.1.4.1 private HConstructor wrap(HConstructor hc) { return relinker.wrap(hc); } 245 cananian 1.1.4.1 private HInitializer wrap(HInitializer hi) { return relinker.wrap(hi); } 246 cananian 1.1.4.1 247 cananian 1.1.4.1 // array wrap/unwrap 248 cananian 1.1.4.1 private HField[] wrap(HField hf[]) { return relinker.wrap(hf); } 249 cananian 1.1.4.1 private HMethod[] wrap(HMethod hm[]) { return relinker.wrap(hm); } 250 cananian 1.1.4.1 private HConstructor[] wrap(HConstructor hc[]) {return relinker.wrap(hc);} 251 cananian 1.1.4.1 252 cananian 1.1.4.1 private HClass[] wrap(HClass[] hc) { 253 cananian 1.1.4.1 HClass[] result = new HClass[hc.length]; 254 cananian 1.1.4.1 for (int i=0; i<result.length; i++) 255 cananian 1.1.4.1 result[i] = wrap(hc[i]); 256 cananian 1.1.4.1 return result; 257 cananian 1.1.4.1 } 258 cananian 1.1.4.1 private HClass[] unwrap(HClass[] hc) { 259 cananian 1.1.4.1 HClass[] result = new HClass[hc.length]; 260 cananian 1.1.4.1 for (int i=0; i<result.length; i++) 261 cananian 1.1.4.1 result[i] = unwrap(hc[i]); 262 cananian 1.1.4.1 return result; 263 cananian 1.1.4.1 } 264 cananian 1.1.4.1 } 265 cananian 1.1.4.1 266 cananian 1.1.4.1 // set emacs indentation style. 267 cananian 1.1.4.1 // Local Variables: 268 cananian 1.1.4.1 // c-basic-offset:2 269 cananian 1.2 // End: