1 29 30 package com.caucho.bytecode; 31 32 import com.caucho.log.Log; 33 34 import java.io.ByteArrayInputStream ; 35 import java.io.IOException ; 36 import java.lang.reflect.*; 37 import java.util.ArrayList ; 38 import java.util.logging.Level ; 39 import java.util.logging.Logger ; 40 41 44 public class JavaMethod extends JMethod { 45 static private final Logger log = Log.open(JavaMethod.class); 46 47 private static final JClass []NULL_CLASS = new JClass[0]; 48 49 private JavaClassLoader _loader; 50 51 private JavaClass _jClass; 52 53 private int _accessFlags; 54 private String _name; 55 private String _descriptor; 56 private JClass []_exceptions = NULL_CLASS; 57 private int _line = -1; 58 59 private ArrayList <Attribute> _attributes = new ArrayList <Attribute>(); 60 61 private JavaAnnotation []_annotations; 62 63 public JavaMethod(JavaClassLoader loader) 64 { 65 _loader = loader; 66 } 67 68 public JavaMethod() 69 { 70 } 71 72 75 public void setJavaClass(JavaClass jClass) 76 { 77 _jClass = jClass; 78 } 79 80 83 public void setName(String name) 84 { 85 _name = name; 86 87 if (_jClass != null) 88 _jClass.getConstantPool().addUTF8(name); 89 } 90 91 94 public String getName() 95 { 96 return _name; 97 } 98 99 102 public int getLine() 103 { 104 if (_line >= 0) 105 return _line; 106 107 Attribute attr = getAttribute("LineNumberTable"); 108 109 if (attr == null) { 110 _line = 0; 111 return _line; 112 } 113 114 _line = 0; 115 return _line; 116 } 117 118 121 public JavaClassLoader getClassLoader() 122 { 123 return _loader; 124 } 125 126 129 public void setAccessFlags(int flags) 130 { 131 _accessFlags = flags; 132 } 133 134 137 public int getAccessFlags() 138 { 139 return _accessFlags; 140 } 141 142 145 public boolean isFinal() 146 { 147 return Modifier.isFinal(getAccessFlags()); 148 } 149 150 153 public boolean isPublic() 154 { 155 return Modifier.isPublic(getAccessFlags()); 156 } 157 158 161 public boolean isPrivate() 162 { 163 return Modifier.isPrivate(getAccessFlags()); 164 } 165 166 169 public boolean isAbstract() 170 { 171 return Modifier.isAbstract(getAccessFlags()); 172 } 173 174 177 public boolean isStatic() 178 { 179 return Modifier.isStatic(getAccessFlags()); 180 } 181 182 185 public void setDescriptor(String descriptor) 186 { 187 _descriptor = descriptor; 188 189 if (_jClass != null) 190 _jClass.getConstantPool().addUTF8(descriptor); 191 } 192 193 196 public String getDescriptor() 197 { 198 return _descriptor; 199 } 200 201 204 public JClass getDeclaringClass() 205 { 206 return _jClass; 207 } 208 209 212 public JClass getReturnType() 213 { 214 String descriptor = getDescriptor(); 215 216 int i = descriptor.lastIndexOf(')'); 217 218 return getClassLoader().descriptorToClass(descriptor, i + 1); 219 } 220 221 224 public JType getGenericReturnType() 225 { 226 SignatureAttribute sigAttr = (SignatureAttribute) getAttribute("Signature"); 227 228 if (sigAttr != null) { 229 String sig = sigAttr.getSignature(); 230 231 int t = sig.lastIndexOf(')'); 232 233 return _loader.parseParameterizedType(sig.substring(t + 1)); 234 } 235 236 return getReturnType(); 237 } 238 239 242 public JClass []getParameterTypes() 243 { 244 String descriptor = getDescriptor(); 245 246 ArrayList <JClass> typeList = new ArrayList <JClass>(); 247 248 int i = 0; 249 while ((i = nextDescriptor(descriptor, i)) >= 0) { 250 typeList.add(getClassLoader().descriptorToClass(descriptor, i)); 251 } 252 253 JClass []types = new JClass[typeList.size()]; 254 255 typeList.toArray(types); 256 257 return types; 258 } 259 260 private int nextDescriptor(String name, int i) 261 { 262 switch (name.charAt(i)) { 263 case ')': 264 return -1; 265 266 case '(': 267 case 'V': 268 case 'Z': 269 case 'C': 270 case 'B': 271 case 'S': 272 case 'I': 273 case 'J': 274 case 'F': 275 case 'D': 276 i += 1; 277 break; 278 279 case '[': 280 return nextDescriptor(name, i + 1); 281 282 case 'L': 283 { 284 int tail = name.indexOf( ';', i); 285 286 if (tail < 0) 287 throw new IllegalStateException (); 288 289 i = tail + 1; 290 } 291 break; 292 293 default: 294 throw new UnsupportedOperationException (name.substring(i)); 295 } 296 297 if (name.length() <= i) 298 return -1; 299 else if (name.charAt(i) == ')') 300 return -1; 301 else 302 return i; 303 } 304 305 308 public void setExceptionTypes(JClass []exceptions) 309 { 310 _exceptions = exceptions; 311 } 312 313 316 public JClass []getExceptionTypes() 317 { 318 return _exceptions; 319 } 320 321 324 public void addAttribute(Attribute attr) 325 { 326 _attributes.add(attr); 327 } 328 329 332 public Attribute removeAttribute(String name) 333 { 334 for (int i = _attributes.size() - 1; i >= 0; i--) { 335 Attribute attr = _attributes.get(i); 336 337 if (attr.getName().equals(name)) { 338 _attributes.remove(i); 339 return attr; 340 } 341 } 342 343 return null; 344 } 345 346 349 public ArrayList <Attribute> getAttributes() 350 { 351 return _attributes; 352 } 353 354 357 public Attribute getAttribute(String name) 358 { 359 for (int i = _attributes.size() - 1; i >= 0; i--) { 360 Attribute attr = _attributes.get(i); 361 362 if (attr.getName().equals(name)) 363 return attr; 364 } 365 366 return null; 367 } 368 369 372 public JAnnotation []getDeclaredAnnotations() 373 { 374 if (_annotations == null) { 375 Attribute attr = getAttribute("RuntimeVisibleAnnotations"); 376 377 if (attr instanceof OpaqueAttribute) { 378 byte []buffer = ((OpaqueAttribute) attr).getValue(); 379 380 try { 381 ByteArrayInputStream is = new ByteArrayInputStream (buffer); 382 383 ConstantPool cp = _jClass.getConstantPool(); 384 385 _annotations = JavaAnnotation.parseAnnotations(is, cp, 386 getClassLoader()); 387 } catch (IOException e) { 388 log.log(Level.FINER, e.toString(), e); 389 } 390 } 391 392 if (_annotations == null) { 393 _annotations = new JavaAnnotation[0]; 394 } 395 } 396 397 return _annotations; 398 } 399 400 403 public CodeAttribute getCode() 404 { 405 for (int i = 0; i < _attributes.size(); i++) { 406 Attribute attr = _attributes.get(i); 407 408 if (attr instanceof CodeAttribute) 409 return (CodeAttribute) attr; 410 } 411 412 return null; 413 } 414 415 416 419 public void write(ByteCodeWriter out) 420 throws IOException 421 { 422 out.writeShort(_accessFlags); 423 out.writeUTF8Const(_name); 424 out.writeUTF8Const(_descriptor); 425 426 out.writeShort(_attributes.size()); 427 for (int i = 0; i < _attributes.size(); i++) { 428 Attribute attr = _attributes.get(i); 429 430 attr.write(out); 431 } 432 } 433 434 437 public JavaMethod export(JavaClass source, JavaClass target) 438 { 439 JavaMethod method = new JavaMethod(_loader); 440 method.setName(_name); 441 method.setDescriptor(_descriptor); 442 method.setAccessFlags(_accessFlags); 443 444 target.getConstantPool().addUTF8(_name); 445 target.getConstantPool().addUTF8(_descriptor); 446 447 for (int i = 0; i < _attributes.size(); i++) { 448 Attribute attr = _attributes.get(i); 449 450 method.addAttribute(attr.export(source, target)); 451 } 452 453 return method; 454 } 455 456 459 public void concatenate(JavaMethod tail) 460 { 461 CodeAttribute codeAttr = getCode(); 462 CodeAttribute tailCodeAttr = tail.getCode(); 463 464 byte []code = codeAttr.getCode(); 465 byte []tailCode = tailCodeAttr.getCode(); 466 467 int codeLength = code.length; 468 469 if ((code[codeLength - 1] & 0xff) == CodeVisitor.RETURN) 470 codeLength = codeLength - 1; 471 472 byte []newCode = new byte[codeLength + tailCode.length]; 473 System.arraycopy(code, 0, newCode, 0, codeLength); 474 System.arraycopy(tailCode, 0, newCode, codeLength, tailCode.length); 475 476 codeAttr.setCode(newCode); 477 478 if (codeAttr.getMaxStack() < tailCodeAttr.getMaxStack()) 479 codeAttr.setMaxStack(tailCodeAttr.getMaxStack()); 480 481 if (codeAttr.getMaxLocals() < tailCodeAttr.getMaxLocals()) 482 codeAttr.setMaxLocals(tailCodeAttr.getMaxLocals()); 483 484 ArrayList <CodeAttribute.ExceptionItem> exns = tailCodeAttr.getExceptions(); 485 for (int i = 0; i < exns.size(); i++) { 486 CodeAttribute.ExceptionItem exn = exns.get(i); 487 488 CodeAttribute.ExceptionItem newExn = new CodeAttribute.ExceptionItem(); 489 490 newExn.setType(exn.getType()); 491 newExn.setStart(exn.getStart() + codeLength); 492 newExn.setEnd(exn.getEnd() + codeLength); 493 newExn.setHandler(exn.getHandler() + codeLength); 494 } 495 } 496 497 public String toString() 498 { 499 return "JavaMethod[" + _name + "]"; 500 } 501 } 502 | Popular Tags |