1 16 17 package org.cojen.classfile; 18 19 import java.io.Serializable ; 20 import java.io.Externalizable ; 21 import java.io.ObjectOutput ; 22 import java.io.ObjectInput ; 23 import java.io.IOException ; 24 import java.io.ObjectStreamException ; 25 import java.lang.reflect.Method ; 26 import java.util.List ; 27 import java.util.ArrayList ; 28 import org.cojen.util.WeakCanonicalSet; 29 30 37 public class MethodDesc extends Descriptor implements Serializable { 38 private static final TypeDesc[] EMPTY_PARAMS = new TypeDesc[0]; 39 40 private final static WeakCanonicalSet mInstances = TypeDesc.cInstances; 42 43 static MethodDesc intern(MethodDesc desc) { 44 return (MethodDesc)mInstances.put(desc); 45 } 46 47 52 public static MethodDesc forArguments(TypeDesc ret, TypeDesc[] params) { 53 if (ret == null) { 54 ret = TypeDesc.VOID; 55 } 56 if (params == null || params.length == 0) { 57 params = EMPTY_PARAMS; 58 } 59 return intern(new MethodDesc(ret, params)); 60 } 61 62 66 public static MethodDesc forDescriptor(String desc) 67 throws IllegalArgumentException 68 { 69 try { 70 int cursor = 0; 71 char c; 72 73 if ((c = desc.charAt(cursor++)) != '(') { 74 throw invalidDescriptor(desc); 75 } 76 77 StringBuffer buf = new StringBuffer (); 78 List list = new ArrayList (); 79 80 while ((c = desc.charAt(cursor++)) != ')') { 81 switch (c) { 82 case 'V': 83 case 'I': 84 case 'C': 85 case 'Z': 86 case 'D': 87 case 'F': 88 case 'J': 89 case 'B': 90 case 'S': 91 buf.append(c); 92 break; 93 case '[': 94 buf.append(c); 95 continue; 96 case 'L': 97 while (true) { 98 buf.append(c); 99 if (c == ';') { 100 break; 101 } 102 c = desc.charAt(cursor++); 103 } 104 break; 105 default: 106 throw invalidDescriptor(desc); 107 } 108 109 list.add(TypeDesc.forDescriptor(buf.toString())); 110 buf.setLength(0); 111 } 112 113 TypeDesc ret = TypeDesc.forDescriptor(desc.substring(cursor)); 114 115 TypeDesc[] tds = new TypeDesc[list.size()]; 116 tds = (TypeDesc[])list.toArray(tds); 117 118 return intern(new MethodDesc(desc, ret, tds)); 119 } catch (NullPointerException e) { 120 throw invalidDescriptor(desc); 121 } catch (IndexOutOfBoundsException e) { 122 throw invalidDescriptor(desc); 123 } 124 } 125 126 public static MethodDesc forMethod(Method method) { 127 Class [] paramClasses = method.getParameterTypes(); 128 TypeDesc[] paramTypes; 129 if (paramClasses == null || paramClasses.length == 0) { 130 paramTypes = EMPTY_PARAMS; 131 } else { 132 paramTypes = new TypeDesc[paramClasses.length]; 133 for (int i=paramClasses.length; --i>=0; ) { 134 paramTypes[i] = TypeDesc.forClass(paramClasses[i]); 135 } 136 } 137 return forArguments(TypeDesc.forClass(method.getReturnType()), paramTypes); 138 } 139 140 private static IllegalArgumentException invalidDescriptor(String desc) { 141 return new IllegalArgumentException ("Invalid descriptor: " + desc); 142 } 143 144 private transient final String mDescriptor; 145 private transient final TypeDesc mRetType; 146 private transient final TypeDesc[] mParams; 147 148 private MethodDesc(TypeDesc ret, TypeDesc[] params) { 149 mDescriptor = generateDescriptor(ret, params); 150 mRetType = ret; 151 mParams = params; 152 } 153 154 private MethodDesc(String desc, TypeDesc ret, TypeDesc[] params) { 155 mDescriptor = desc; 156 mRetType = ret; 157 mParams = params; 158 } 159 160 163 public String getDescriptor() { 164 return mDescriptor; 165 } 166 167 170 172 175 public TypeDesc getReturnType() { 176 return mRetType; 177 } 178 179 public int getParameterCount() { 180 return mParams.length; 181 } 182 183 public TypeDesc[] getParameterTypes() { 184 TypeDesc[] params = mParams; 185 return (params != EMPTY_PARAMS) ? (TypeDesc[])params.clone() : params; 186 } 187 188 193 public String toMethodSignature(String name) { 194 return toMethodSignature(name, false); 195 } 196 197 204 public String toMethodSignature(String name, boolean varargs) { 205 StringBuffer buf = new StringBuffer (); 206 buf.append(mRetType.getFullName()); 207 buf.append(' '); 208 buf.append(name); 209 buf.append('('); 210 211 TypeDesc[] params = mParams; 212 for (int i=0; i<params.length; i++) { 213 if (i > 0) { 214 buf.append(", "); 215 } 216 TypeDesc param = params[i]; 217 if (varargs && param.isArray() && i == (params.length - 1)) { 218 buf.append(param.getComponentType().getFullName()); 219 buf.append("..."); 220 } else { 221 buf.append(param.getFullName()); 222 } 223 } 224 225 return buf.append(')').toString(); 226 } 227 228 public String toString() { 229 return mDescriptor; 231 } 232 233 public int hashCode() { 234 return mDescriptor.hashCode(); 235 } 236 237 public boolean equals(Object other) { 238 if (this == other) { 239 return true; 240 } 241 if (other instanceof MethodDesc) { 242 return ((MethodDesc)other).mDescriptor.equals(mDescriptor); 243 } 244 return false; 245 } 246 247 Object writeReplace() throws ObjectStreamException { 248 return new External(mDescriptor); 249 } 250 251 private static String generateDescriptor(TypeDesc ret, TypeDesc[] params) { 252 int length = ret.getDescriptor().length() + 2; 253 int paramsLength = params.length; 254 for (int i=paramsLength; --i >=0; ) { 255 length += params[i].getDescriptor().length(); 256 } 257 char[] buf = new char[length]; 258 buf[0] = '('; 259 int index = 1; 260 String paramDesc; 261 for (int i=0; i<paramsLength; i++) { 262 paramDesc = params[i].getDescriptor(); 263 int paramDescLength = paramDesc.length(); 264 paramDesc.getChars(0, paramDescLength, buf, index); 265 index += paramDescLength; 266 } 267 buf[index++] = ')'; 268 paramDesc = ret.getDescriptor(); 269 paramDesc.getChars(0, paramDesc.length(), buf, index); 270 return new String (buf); 271 } 272 273 private static class External implements Externalizable { 274 private String mDescriptor; 275 276 public External() { 277 } 278 279 public External(String desc) { 280 mDescriptor = desc; 281 } 282 283 public void writeExternal(ObjectOutput out) throws IOException { 284 out.writeUTF(mDescriptor); 285 } 286 287 public void readExternal(ObjectInput in) throws IOException { 288 mDescriptor = in.readUTF(); 289 } 290 291 public Object readResolve() throws ObjectStreamException { 292 return forDescriptor(mDescriptor); 293 } 294 } 295 } 296 | Popular Tags |