1 cananian 1.1.2.1 // HClassArraySyn.java, created Fri Oct 20 17:34:37 2000 by cananian
  2 cananian 1.1.2.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1 package harpoon.ClassFile;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.1 import harpoon.Util.Util;
  7 cananian 1.1.2.1 
  8 cananian 1.1.2.1 import java.util.ArrayList;
  9 cananian 1.1.2.5 import java.util.Iterator;
 10 cananian 1.1.2.1 import java.util.List;
 11 cananian 1.1.2.1 /**
 12 cananian 1.1.2.1  * <code>HClassArraySyn</code> is a simple subclass of
 13 cananian 1.1.2.1  * <code>HClassArray</code> which allows you to add methods
 14 cananian 1.1.2.1  * (not fields, class initializers, or constructors) to
 15 cananian 1.1.2.1  * an array type.
 16 cananian 1.1.2.1  * 
 17 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 18 cananian 1.5      * @version $Id: HClassArraySyn.java,v 1.5 2004/02/08 03:21:10 cananian Exp $
 19 cananian 1.1.2.1  */
 20 cananian 1.1.2.1 class HClassArraySyn extends HClassArray implements HClassMutator {
 21 cananian 1.1.2.4     final List declaredMethods = new ArrayList(4);
 22 cananian 1.1.2.1     
 23 cananian 1.1.2.1     /** Creates a <code>HClassArraySyn</code>. */
 24 cananian 1.1.2.1     HClassArraySyn(Linker linker, HClass baseType, int dims) {
 25 cananian 1.1.2.6         this(linker, baseType, dims, true/*init w/ clone method*/);
 26 cananian 1.1.2.6     }
 27 cananian 1.1.2.6     private HClassArraySyn(Linker linker, HClass baseType, int dims,
 28 cananian 1.1.2.6                            boolean init) {
 29 cananian 1.1.2.1         super(linker, baseType, dims);
 30 cananian 1.1.2.6         if (init) // we skip this step when restoring from serialized form.
 31 cananian 1.1.2.6             declaredMethods.add // even clone method is mutable.
 32 cananian 1.1.2.6                 (new HMethodSyn(this, cloneMethod.getName(), cloneMethod));
 33 cananian 1.1.2.1     }
 34 cananian 1.1.2.1     /** Allow mutation. */
 35 cananian 1.1.2.1     public HClassMutator getMutator() { return this; }
 36 cananian 1.1.2.3     public HMethod[] getDeclaredMethods() {
 37 cananian 1.1.2.3         return (HMethod[])
 38 cananian 1.1.2.3             declaredMethods.toArray(new HMethod[declaredMethods.size()]);
 39 cananian 1.1.2.3     }
 40 cananian 1.1.2.1 
 41 cananian 1.1.2.1     // Allowed mutations.  -----------------------------------------
 42 cananian 1.1.2.1     public HMethod addDeclaredMethod(String name, String descriptor) {
 43 cananian 1.3.2.1         assert !name.equals("<init>") && !name.equals("<clinit>");
 44 cananian 1.1.2.1         return addDeclaredMethod0(new HMethodSyn(this, name, descriptor));
 45 cananian 1.1.2.1     }
 46 cananian 1.1.2.1     public HMethod addDeclaredMethod(String name, HClass[] paramTypes,
 47 cananian 1.1.2.1                                      HClass returnType) {
 48 cananian 1.3.2.1         assert !name.equals("<init>") && !name.equals("<clinit>");
 49 cananian 1.3.2.1         assert checkLinker(returnType);
 50 cananian 1.1.2.1         for (int i=0; i<paramTypes.length; i++)
 51 cananian 1.3.2.1             assert checkLinker(paramTypes[i]);
 52 cananian 1.1.2.1         return addDeclaredMethod0(new HMethodSyn(this, name, paramTypes,
 53 cananian 1.1.2.1                                                  returnType));
 54 cananian 1.1.2.1     }
 55 cananian 1.1.2.1     public HMethod addDeclaredMethod(String name, HMethod template) {
 56 cananian 1.3.2.1         assert !name.equals("<init>") && !name.equals("<clinit>");
 57 cananian 1.1.2.1         return addDeclaredMethod0(new HMethodSyn(this, name, template));
 58 cananian 1.1.2.1     }
 59 cananian 1.1.2.1     /** single implementation. */
 60 cananian 1.1.2.1     private HMethod addDeclaredMethod0(HMethodSyn hm) {
 61 cananian 1.3.2.1         assert hm.getDeclaringClass()==this;
 62 cananian 1.1.2.1         if (declaredMethods.contains(hm))
 63 cananian 1.1.2.1             throw new DuplicateMemberException("Method "+hm+" in "+this);
 64 cananian 1.1.2.1         declaredMethods.add(hm);
 65 cananian 1.1.2.1         hasBeenModified=true; // flag the modification
 66 cananian 1.1.2.1         return hm;
 67 cananian 1.1.2.1     }
 68 cananian 1.1.2.1     public void removeDeclaredMethod(HMethod m) throws NoSuchMethodError {
 69 cananian 1.1.2.1         if (declaredMethods.remove(m)) {
 70 cananian 1.1.2.1             hasBeenModified=true; // flag the modification
 71 cananian 1.1.2.1             return;
 72 cananian 1.1.2.1         }
 73 cananian 1.1.2.1         throw new NoSuchMemberException("Method "+m+" in "+this);
 74 cananian 1.1.2.1     }
 75 cananian 1.1.2.1 
 76 cananian 1.1.2.1     // Unallowed mutations.  ---------------------------------------
 77 cananian 1.1.2.1     public HField addDeclaredField(String name, HClass type)
 78 cananian 1.1.2.1         throws DuplicateMemberException {
 79 cananian 1.1.2.1         throw new Error("Adding fields to arrays is not allowed.");
 80 cananian 1.1.2.1     }
 81 cananian 1.1.2.1     public HField addDeclaredField(String name, String descriptor)
 82 cananian 1.1.2.1         throws DuplicateMemberException {
 83 cananian 1.1.2.1         throw new Error("Adding fields to arrays is not allowed.");
 84 cananian 1.1.2.1     }
 85 cananian 1.1.2.1     public HField addDeclaredField(String name, HField template)
 86 cananian 1.1.2.1         throws DuplicateMemberException {
 87 cananian 1.1.2.1         throw new Error("Adding fields to arrays is not allowed.");
 88 cananian 1.1.2.1     }
 89 cananian 1.1.2.1     public void removeDeclaredField(HField f) throws NoSuchMemberException {
 90 cananian 1.1.2.1         if (f==lengthField)
 91 cananian 1.1.2.1             throw new Error("Removing the length fields from an array is not "+
 92 cananian 1.1.2.1                             "allowed.");
 93 cananian 1.1.2.1         else throw new NoSuchMemberException(f.toString());
 94 cananian 1.1.2.1     }
 95 cananian 1.1.2.1     public HInitializer addClassInitializer() throws DuplicateMemberException {
 96 cananian 1.1.2.1         throw new Error("Adding a class initializer to an array is not "+
 97 cananian 1.1.2.1                         "allowed.");
 98 cananian 1.1.2.1     }
 99 cananian 1.1.2.1     public void removeClassInitializer(HInitializer m)
100 cananian 1.1.2.1         throws NoSuchMemberException {
101 cananian 1.1.2.1         throw new NoSuchMemberException(m.toString());
102 cananian 1.1.2.1     }
103 cananian 1.1.2.1     public HConstructor addConstructor(String descriptor)
104 cananian 1.1.2.1         throws DuplicateMemberException {
105 cananian 1.1.2.1         throw new Error("Adding a constructor to an array is not allowed.");
106 cananian 1.1.2.1     }
107 cananian 1.1.2.1     public HConstructor addConstructor(HClass[] paramTypes)
108 cananian 1.1.2.1         throws DuplicateMemberException {
109 cananian 1.1.2.1         throw new Error("Adding a constructor to an array is not allowed.");
110 cananian 1.1.2.1     }
111 cananian 1.1.2.1     public HConstructor addConstructor(HConstructor template)
112 cananian 1.1.2.1         throws DuplicateMemberException {
113 cananian 1.1.2.1         throw new Error("Adding a constructor to an array is not allowed.");
114 cananian 1.1.2.1     }
115 cananian 1.1.2.1     public void removeConstructor(HConstructor c)
116 cananian 1.1.2.1         throws NoSuchMemberException {
117 cananian 1.1.2.1         throw new NoSuchMemberException(c.toString());
118 cananian 1.1.2.1     }
119 cananian 1.1.2.1     public void addInterface(HClass in) {
120 cananian 1.1.2.1         throw new Error("Not allowed to add interfaces to an array.");
121 cananian 1.1.2.1     }
122 cananian 1.1.2.1     public void removeInterface(HClass in)
123 cananian 1.1.2.1         throws NoSuchClassException {
124 cananian 1.1.2.1         throw new Error("Not allowed to remove interfaces from an array.");
125 cananian 1.1.2.1     }
126 cananian 1.1.2.1     public void removeAllInterfaces() {
127 cananian 1.1.2.1         throw new Error("Not allowed to remove interfaces from an array.");
128 cananian 1.1.2.1     }
129 cananian 1.1.2.1     public void addModifiers(int m) {
130 cananian 1.1.2.1         throw new Error("Not allowed to change the modifiers of an array.");
131 cananian 1.1.2.1     }
132 cananian 1.1.2.1     public void setModifiers(int m) {
133 cananian 1.1.2.1         throw new Error("Not allowed to change the modifiers of an array.");
134 cananian 1.1.2.1     }
135 cananian 1.1.2.1     public void removeModifiers(int m) {
136 cananian 1.1.2.1         throw new Error("Not allowed to change the modifiers of an array.");
137 cananian 1.1.2.1     }
138 cananian 1.1.2.1     public void setSuperclass(HClass sc) {
139 cananian 1.1.2.1         throw new Error("Not allowed to change the superclass of an array.");
140 cananian 1.1.2.1     }
141 cananian 1.1.2.1     public void setSourceFile(String sourcefilename) {
142 cananian 1.1.2.1         throw new Error("Not allowed to reset the source file of an array.");
143 cananian 1.1.2.1     }
144 cananian 1.1.2.1 
145 cananian 1.1.2.1     //----------------------------------------------------------
146 cananian 1.1.2.1     // assertion helper.
147 cananian 1.1.2.1     private boolean checkLinker(HClass hc) {
148 cananian 1.1.2.1         return hc.isPrimitive() || hc.getLinker()==getLinker();
149 cananian 1.1.2.1     }
150 cananian 1.1.2.1     //----------------------------------------------------------
151 cananian 1.1.2.4 
152 cananian 1.1.2.4     /** Serializable interface. */
153 cananian 1.1.2.4     public Object writeReplace() {
154 cananian 1.1.2.5         return new Stub(this);
155 cananian 1.1.2.4     }
156 cananian 1.1.2.4     private static final class Stub implements java.io.Serializable {
157 cananian 1.1.2.4         private final Linker linker;
158 cananian 1.1.2.4         private final HClass baseType;
159 cananian 1.1.2.4         private final int dims;
160 cananian 1.1.2.4         private final List declaredMethods;
161 cananian 1.1.2.4         private final boolean modified;
162 cananian 1.1.2.4         Stub(HClassArraySyn c) { // store salient information.
163 cananian 1.1.2.4             this.linker = c.getLinker();
164 cananian 1.1.2.4             this.baseType = c.baseType;
165 cananian 1.1.2.4             this.dims = c.dims;
166 cananian 1.1.2.4             this.modified = c.hasBeenModified;
167 cananian 1.1.2.6             this.declaredMethods = new ArrayList(c.declaredMethods.size());
168 cananian 1.5                 for (Object hmO : c.declaredMethods) {
169 cananian 1.5                     HMethod hm = (HMethod) hmO;
170 cananian 1.1.2.5                 this.declaredMethods.add(new HClassSyn.MethodStub(hm));
171 cananian 1.1.2.5             }
172 cananian 1.1.2.4         }
173 cananian 1.1.2.4         public Object readResolve() {
174 cananian 1.1.2.6             HClassArraySyn c=new HClassArraySyn(linker, baseType, dims, false);
175 cananian 1.1.2.5             for (Iterator it=declaredMethods.iterator(); it.hasNext(); ) {
176 cananian 1.1.2.5                 HMethod hm = ((HClassSyn.MethodStub)it.next()).reconstruct(c);
177 cananian 1.1.2.5                 c.declaredMethods.add(hm);
178 cananian 1.1.2.5             }
179 cananian 1.1.2.4             c.hasBeenModified = this.modified;
180 cananian 1.1.2.4             return c;
181 cananian 1.1.2.4         }
182 cananian 1.1.2.4     }
183 cananian 1.2     }