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: