1 33 34 package bsh; 35 36 import bsh.org.objectweb.asm.*; 37 import bsh.org.objectweb.asm.Type; 38 39 import java.lang.reflect.*; 40 import java.util.ArrayList ; 41 import java.util.List ; 42 43 75 80 public class ClassGeneratorUtil implements Constants 81 { 82 84 static final String BSHSTATIC="_bshStatic"; 85 86 88 static final String BSHTHIS="_bshThis"; 89 90 92 static final String BSHSUPER="_bshSuper"; 93 94 95 static final String BSHINIT="_bshInstanceInitializer"; 96 97 98 static final String BSHCONSTRUCTORS="_bshConstructors"; 99 100 102 static final int DEFAULTCONSTRUCTOR = -1; 103 104 static final String OBJECT= "Ljava/lang/Object;"; 105 106 String className; 107 108 String fqClassName; 109 Class superClass; 110 String superClassName; 111 Class [] interfaces; 112 Variable [] vars; 113 Constructor [] superConstructors; 114 DelayedEvalBshMethod [] constructors; 115 DelayedEvalBshMethod [] methods; 116 NameSpace classStaticNameSpace; 117 Modifiers classModifiers; 118 boolean isInterface; 119 120 123 public ClassGeneratorUtil( 124 Modifiers classModifiers, String className, String packageName, 125 Class superClass, Class [] interfaces, Variable [] vars, 126 DelayedEvalBshMethod [] bshmethods, NameSpace classStaticNameSpace, 127 boolean isInterface 128 ) 129 { 130 this.classModifiers = classModifiers; 131 this.className = className; 132 if ( packageName != null ) 133 this.fqClassName = packageName.replace('.','/') + "/" + className; 134 else 135 this.fqClassName = className; 136 if ( superClass == null ) 137 superClass = Object .class; 138 this.superClass = superClass; 139 this.superClassName = Type.getInternalName( superClass ); 140 if ( interfaces == null ) 141 interfaces = new Class [0]; 142 this.interfaces = interfaces; 143 this.vars = vars; 144 this.classStaticNameSpace = classStaticNameSpace; 145 this.superConstructors = superClass.getDeclaredConstructors(); 146 147 List consl = new ArrayList (); 149 List methodsl = new ArrayList (); 150 String classBaseName = getBaseName( className ); for( int i=0; i< bshmethods.length; i++ ) 152 if ( bshmethods[i].getName().equals( classBaseName ) ) 153 consl.add( bshmethods[i] ); 154 else 155 methodsl.add( bshmethods[i] ); 156 157 this.constructors = (DelayedEvalBshMethod [])consl.toArray( 158 new DelayedEvalBshMethod[0] ); 159 this.methods = (DelayedEvalBshMethod [])methodsl.toArray( 160 new DelayedEvalBshMethod[0] ); 161 162 try { 163 classStaticNameSpace.setLocalVariable( 164 BSHCONSTRUCTORS, constructors, false ); 165 } catch ( UtilEvalError e ) { 166 throw new InterpreterError("can't set cons var"); 167 } 168 169 this.isInterface = isInterface; 170 } 171 172 175 public byte [] generateClass() 176 { 177 int classMods = getASMModifiers( classModifiers ) | ACC_PUBLIC; 179 if ( isInterface ) 180 classMods |= ACC_INTERFACE; 181 182 String [] interfaceNames = new String [interfaces.length]; 183 for(int i=0; i<interfaces.length; i++) 184 interfaceNames[i]=Type.getInternalName( interfaces[i] ); 185 186 String sourceFile = "BeanShell Generated via ASM (www.objectweb.org)"; 187 ClassWriter cw = new ClassWriter(false); 188 cw.visit( classMods, fqClassName, superClassName, 189 interfaceNames, sourceFile ); 190 191 if ( !isInterface ) 192 { 193 generateField( 195 BSHTHIS+className, "Lbsh/This;", ACC_PUBLIC, cw); 196 197 generateField( 199 BSHSTATIC+className, "Lbsh/This;", ACC_PUBLIC+ACC_STATIC, cw); 200 } 201 202 for( int i=0; i<vars.length; i++) 204 { 205 String type = vars[i].getTypeDescriptor(); 206 207 if ( vars[i].hasModifier("private") || type == null ) 210 continue; 211 212 int modifiers; 213 if ( isInterface ) 214 modifiers = ACC_PUBLIC | ACC_STATIC | ACC_FINAL; 215 else 216 modifiers = getASMModifiers( vars[i].getModifiers() ); 217 218 generateField( vars[i].getName(), type, modifiers , cw ); 219 } 220 221 boolean hasConstructor = false; 223 for( int i=0; i<constructors.length; i++) 224 { 225 if ( constructors[i].hasModifier("private") ) 227 continue; 228 229 int modifiers = getASMModifiers( constructors[i].getModifiers() ); 230 generateConstructor( 231 i, constructors[i].getParamTypeDescriptors(), modifiers, cw ); 232 hasConstructor = true; 233 } 234 235 if ( !isInterface && !hasConstructor ) 237 generateConstructor( 238 DEFAULTCONSTRUCTOR, new String [0], ACC_PUBLIC, cw ); 239 240 for( int i=0; i<methods.length; i++) 242 { 243 String returnType = methods[i].getReturnTypeDescriptor(); 244 245 if ( methods[i].hasModifier("private") ) 247 continue; 248 249 int modifiers = getASMModifiers( methods[i].getModifiers() ); 250 if ( isInterface ) 251 modifiers |= ( ACC_PUBLIC | ACC_ABSTRACT ); 252 253 generateMethod( className, fqClassName, 254 methods[i].getName(), returnType, 255 methods[i].getParamTypeDescriptors(), modifiers, cw ); 256 257 boolean isStatic = (modifiers & ACC_STATIC) > 0 ; 258 boolean overridden = classContainsMethod( 259 superClass, methods[i].getName(), 260 methods[i].getParamTypeDescriptors() ) ; 261 if ( !isStatic && overridden ) 262 generateSuperDelegateMethod( superClassName, 263 methods[i].getName(), returnType, 264 methods[i].getParamTypeDescriptors(), modifiers, cw ); 265 } 266 267 return cw.toByteArray(); 268 } 269 270 273 static int getASMModifiers( Modifiers modifiers ) 274 { 275 int mods = 0; 276 if ( modifiers == null ) 277 return mods; 278 279 if ( modifiers.hasModifier("public") ) 280 mods += ACC_PUBLIC; 281 if ( modifiers.hasModifier("protected") ) 282 mods += ACC_PROTECTED; 283 if ( modifiers.hasModifier("static") ) 284 mods += ACC_STATIC; 285 if ( modifiers.hasModifier("synchronized") ) 286 mods += ACC_SYNCHRONIZED; 287 if ( modifiers.hasModifier("abstract") ) 288 mods += ACC_ABSTRACT; 289 290 return mods; 291 } 292 293 296 static void generateField( 297 String fieldName, String type, int modifiers, ClassWriter cw ) 298 { 299 cw.visitField( modifiers, fieldName, type, null ); 300 } 301 302 309 static void generateMethod( 310 String className, String fqClassName, String methodName, 311 String returnType, String [] paramTypes, int modifiers, ClassWriter cw ) 312 { 313 String [] exceptions = null; 314 boolean isStatic = (modifiers & ACC_STATIC) != 0 ; 315 316 if ( returnType == null ) returnType = OBJECT; 318 319 String methodDescriptor = getMethodDescriptor( returnType, paramTypes ); 320 321 CodeVisitor cv = cw.visitMethod( 323 modifiers, methodName, methodDescriptor, exceptions ); 324 325 if ( (modifiers & ACC_ABSTRACT) != 0 ) 326 return; 327 328 if ( isStatic ) 330 { 331 cv.visitFieldInsn( 332 GETSTATIC, fqClassName, BSHSTATIC+className, "Lbsh/This;" ); 333 }else 334 { 335 cv.visitVarInsn( ALOAD, 0 ); 337 338 cv.visitFieldInsn( 340 GETFIELD, fqClassName, BSHTHIS+className, "Lbsh/This;" ); 341 } 342 343 cv.visitLdcInsn( methodName ); 345 346 generateParameterReifierCode( paramTypes, isStatic, cv ); 348 349 cv.visitInsn(ACONST_NULL); cv.visitInsn(ACONST_NULL); cv.visitInsn(ACONST_NULL); 354 cv.visitInsn(ICONST_1); 356 357 cv.visitMethodInsn( 359 INVOKEVIRTUAL, "bsh/This", "invokeMethod", 360 Type.getMethodDescriptor( 361 Type.getType(Object .class), 362 new Type [] { 363 Type.getType(String .class), 364 Type.getType(Object [].class), 365 Type.getType(Interpreter.class), 366 Type.getType(CallStack.class), 367 Type.getType(SimpleNode.class), 368 Type.getType(Boolean.TYPE) 369 } 370 ) 371 ); 372 373 cv.visitMethodInsn( 375 INVOKESTATIC, "bsh/Primitive", "unwrap", 376 "(Ljava/lang/Object;)Ljava/lang/Object;" ); 377 378 generateReturnCode( returnType, cv ); 380 381 cv.visitMaxs( 20, 20 ); 383 } 384 385 388 void generateConstructor( 389 int index, String [] paramTypes, int modifiers, ClassWriter cw ) 390 { 391 392 final int argsVar = paramTypes.length+1; 393 394 final int consArgsVar = paramTypes.length+2; 395 396 String [] exceptions = null; 397 String methodDescriptor = getMethodDescriptor( "V", paramTypes ); 398 399 CodeVisitor cv = 401 cw.visitMethod( modifiers, "<init>", methodDescriptor, exceptions ); 402 403 generateParameterReifierCode( paramTypes, false, cv ); 405 cv.visitVarInsn( ASTORE, argsVar ); 406 407 generateConstructorSwitch( index, argsVar, consArgsVar, cv ); 409 410 412 cv.visitVarInsn( ALOAD, 0 ); 414 415 cv.visitLdcInsn( className ); 417 418 cv.visitVarInsn( ALOAD, argsVar ); 420 421 cv.visitMethodInsn( 423 INVOKESTATIC, "bsh/ClassGeneratorUtil", "initInstance", 424 "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V"); 425 426 cv.visitInsn( RETURN ); 427 428 cv.visitMaxs( 20, 20 ); 430 } 431 432 445 void generateConstructorSwitch( 446 int consIndex, int argsVar, int consArgsVar, CodeVisitor cv ) 447 { 448 Label defaultLabel = new Label(); 449 Label endLabel = new Label(); 450 int cases = superConstructors.length + constructors.length ; 451 452 Label [] labels = new Label[ cases ]; 453 for(int i=0; i<cases; i++) 454 labels[i]=new Label(); 455 456 459 cv.visitLdcInsn( superClass.getName() ); 462 cv.visitFieldInsn( 464 GETSTATIC, fqClassName, BSHSTATIC+className, "Lbsh/This;" ); 465 466 cv.visitVarInsn( ALOAD, argsVar ); 468 469 cv.visitIntInsn( BIPUSH, consIndex ); 471 472 cv.visitMethodInsn( 474 INVOKESTATIC, "bsh/ClassGeneratorUtil", "getConstructorArgs", 475 "(Ljava/lang/String;Lbsh/This;[Ljava/lang/Object;I)" 476 +"Lbsh/ClassGeneratorUtil$ConstructorArgs;" 477 ); 478 479 cv.visitVarInsn( ASTORE, consArgsVar ); 481 482 484 cv.visitVarInsn( ALOAD, consArgsVar ); 486 cv.visitFieldInsn( 487 GETFIELD, "bsh/ClassGeneratorUtil$ConstructorArgs", "selector", "I" ); 488 489 cv.visitTableSwitchInsn( 491 0, cases-1, defaultLabel, labels ); 492 493 int index = 0; 495 for( int i=0; i< superConstructors.length; i++, index++) 496 doSwitchBranch( index, superClassName, 497 getTypeDescriptors( superConstructors[i].getParameterTypes() ), 498 endLabel, labels, consArgsVar, cv ); 499 for( int i=0; i< constructors.length; i++, index++) 500 doSwitchBranch( index, fqClassName, 501 constructors[i].getParamTypeDescriptors(), 502 endLabel, labels, consArgsVar, cv ); 503 504 cv.visitLabel( defaultLabel ); 506 cv.visitVarInsn( ALOAD, 0 ); cv.visitMethodInsn( INVOKESPECIAL, superClassName, "<init>", "()V" ); 509 510 cv.visitLabel( endLabel ); 512 } 513 514 520 static void doSwitchBranch( 521 int index, String targetClassName, String [] paramTypes, 522 Label endLabel, Label [] labels, int consArgsVar, CodeVisitor cv 523 ) 524 { 525 cv.visitLabel( labels[index] ); 526 cv.visitVarInsn( ALOAD, 0 ); 529 for (int i=0; i<paramTypes.length; i++) 531 { 532 String type = paramTypes[i]; 533 String method = null; 534 if ( type.equals("Z") ) 535 method = "getBoolean"; 536 else if ( type.equals("B") ) 537 method = "getByte"; 538 else if ( type.equals("C") ) 539 method = "getChar"; 540 else if ( type.equals("S") ) 541 method = "getShort"; 542 else if ( type.equals("I") ) 543 method = "getInt"; 544 else if ( type.equals("J") ) 545 method = "getLong"; 546 else if ( type.equals("D") ) 547 method = "getDouble"; 548 else if ( type.equals("F") ) 549 method = "getFloat"; 550 else 551 method = "getObject"; 552 553 cv.visitVarInsn( ALOAD, consArgsVar ); String className = "bsh/ClassGeneratorUtil$ConstructorArgs"; 556 String retType; 557 if ( method.equals("getObject") ) 558 retType = OBJECT; 559 else 560 retType = type; 561 cv.visitMethodInsn(INVOKEVIRTUAL, className, method, "()"+retType); 562 if ( method.equals("getObject") ) 564 cv.visitTypeInsn( CHECKCAST, descriptorToClassName(type) ); 565 } 566 567 String descriptor = getMethodDescriptor( "V", paramTypes ); 569 cv.visitMethodInsn( 570 INVOKESPECIAL, targetClassName, "<init>", descriptor ); 571 cv.visitJumpInsn( GOTO, endLabel ); 572 } 573 574 static String getMethodDescriptor( String returnType, String [] paramTypes ) 575 { 576 StringBuffer sb = new StringBuffer ("("); 577 for(int i=0; i<paramTypes.length; i++) 578 sb.append(paramTypes[i]); 579 sb.append(")"+returnType); 580 return sb.toString(); 581 } 582 583 589 static void generateSuperDelegateMethod( String superClassName, String methodName, 591 String returnType, String [] paramTypes, int modifiers, ClassWriter cw ) 592 { 593 String [] exceptions = null; 594 595 if ( returnType == null ) returnType = OBJECT; 597 598 String methodDescriptor = getMethodDescriptor( returnType, paramTypes ); 599 600 CodeVisitor cv = cw.visitMethod( 602 modifiers, "_bshSuper"+methodName, methodDescriptor, exceptions ); 603 604 cv.visitVarInsn(ALOAD, 0); 605 int localVarIndex = 1; 607 for (int i = 0; i < paramTypes.length; ++i) 608 { 609 if ( isPrimitive( paramTypes[i]) ) 610 cv.visitVarInsn(ILOAD, localVarIndex); 611 else 612 cv.visitVarInsn(ALOAD, localVarIndex); 613 localVarIndex += 614 ( (paramTypes[i].equals("D") || paramTypes[i].equals("J")) 615 ? 2 : 1 ); 616 } 617 618 cv.visitMethodInsn( INVOKESPECIAL, 619 superClassName, methodName, methodDescriptor ); 620 621 generatePlainReturnCode( returnType, cv ); 622 623 cv.visitMaxs( 20, 20 ); 625 } 626 627 boolean classContainsMethod( 628 Class clas, String methodName, String [] paramTypes ) 629 { 630 while( clas != null ) 631 { 632 Method [] methods = clas.getDeclaredMethods(); 633 for( int i =0; i<methods.length; i++ ) 634 { 635 if ( methods[i].getName().equals(methodName) ) 636 { 637 String [] methodParamTypes = 638 getTypeDescriptors( methods[i].getParameterTypes() ); 639 boolean found = true; 640 for( int j=0; j<methodParamTypes.length; j++) 641 { 642 if ( ! paramTypes[j].equals( methodParamTypes[j] ) ) { 643 found = false; 644 break; 645 } 646 } 647 if ( found ) 648 return true; 649 } 650 } 651 652 clas = clas.getSuperclass(); 653 } 654 655 return false; 656 } 657 658 661 static void generatePlainReturnCode( String returnType, CodeVisitor cv ) 662 { 663 if ( returnType.equals("V") ) 664 cv.visitInsn( RETURN ); 665 else 666 if ( isPrimitive( returnType ) ) 667 { 668 int opcode = IRETURN; 669 if ( returnType.equals("D") ) 670 opcode = DRETURN; 671 else if ( returnType.equals("F") ) 672 opcode = FRETURN; 673 else if ( returnType.equals("J") ) opcode = LRETURN; 675 676 cv.visitInsn(opcode); 677 } 678 else { 679 cv.visitTypeInsn( CHECKCAST, descriptorToClassName(returnType) ); 680 cv.visitInsn( ARETURN ); 681 } 682 } 683 684 695 public static void generateParameterReifierCode ( 696 String [] paramTypes, boolean isStatic, final CodeVisitor cv ) 697 { 698 cv.visitIntInsn(SIPUSH, paramTypes.length); 699 cv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); 700 int localVarIndex = isStatic ? 0 : 1; 701 for (int i = 0; i < paramTypes.length; ++i) 702 { 703 String param = paramTypes[i]; 704 cv.visitInsn(DUP); 705 cv.visitIntInsn(SIPUSH, i); 706 if ( isPrimitive( param ) ) 707 { 708 int opcode; 709 if (param.equals("F")) { 710 opcode = FLOAD; 711 } else if (param.equals("D")) { 712 opcode = DLOAD; 713 } else if (param.equals("J")) { 714 opcode = LLOAD; 715 } else { 716 opcode = ILOAD; 717 } 718 719 String type = "bsh/Primitive"; 720 cv.visitTypeInsn( NEW, type ); 721 cv.visitInsn(DUP); 722 cv.visitVarInsn(opcode, localVarIndex); 723 String desc = param; cv.visitMethodInsn( 725 INVOKESPECIAL, type, "<init>", "(" + desc + ")V"); 726 } else { 727 cv.visitVarInsn( ALOAD, localVarIndex ); 733 } 734 cv.visitInsn(AASTORE); 735 localVarIndex += 736 ( (param.equals("D") || param.equals("J")) ? 2 : 1 ); 737 } 738 } 739 740 749 public static void generateReturnCode ( 750 String returnType, CodeVisitor cv ) 751 { 752 if ( returnType.equals("V") ) 753 { 754 cv.visitInsn(POP); 755 cv.visitInsn(RETURN); 756 } 757 else if ( isPrimitive( returnType ) ) 758 { 759 int opcode = IRETURN; 760 String type; 761 String meth; 762 if ( returnType.equals("B") ) { 763 type = "java/lang/Byte"; 764 meth = "byteValue"; 765 } else if (returnType.equals("I") ) { 766 type = "java/lang/Integer"; 767 meth = "intValue"; 768 } else if (returnType.equals("Z") ) { 769 type = "java/lang/Boolean"; 770 meth = "booleanValue"; 771 } else if (returnType.equals("D") ) { 772 opcode = DRETURN; 773 type = "java/lang/Double"; 774 meth = "doubleValue"; 775 } else if (returnType.equals("F") ) { 776 opcode = FRETURN; 777 type = "java/lang/Float"; 778 meth = "floatValue"; 779 } else if (returnType.equals("J") ) { 780 opcode = LRETURN; 781 type = "java/lang/Long"; 782 meth = "longValue"; 783 } else if (returnType.equals("C") ) { 784 type = "java/lang/Character"; 785 meth = "charValue"; 786 } else { 787 type = "java/lang/Short"; 788 meth = "shortValue"; 789 } 790 791 String desc = returnType; 792 cv.visitTypeInsn( CHECKCAST, type ); cv.visitMethodInsn( INVOKEVIRTUAL, type, meth, "()" + desc ); 794 cv.visitInsn(opcode); 795 } else 796 { 797 cv.visitTypeInsn( CHECKCAST, descriptorToClassName(returnType) ); 798 cv.visitInsn(ARETURN); 799 } 800 } 801 802 813 public static ConstructorArgs getConstructorArgs( 814 String superClassName, This classStaticThis, 815 Object [] consArgs, int index ) 816 { 817 DelayedEvalBshMethod [] constructors; 818 try { 819 constructors = 820 (DelayedEvalBshMethod [])classStaticThis.getNameSpace() 821 .getVariable( BSHCONSTRUCTORS ); 822 } catch ( Exception e ) { 823 throw new InterpreterError( 824 "unable to get instance initializer: "+e ); 825 } 826 827 if ( index == DEFAULTCONSTRUCTOR ) return ConstructorArgs.DEFAULT; 830 DelayedEvalBshMethod constructor = constructors[index]; 831 832 if ( constructor.methodBody.jjtGetNumChildren() == 0 ) 833 return ConstructorArgs.DEFAULT; 835 String altConstructor = null; 837 BSHArguments argsNode = null; 838 SimpleNode firstStatement = 839 (SimpleNode)constructor.methodBody.jjtGetChild(0); 840 if ( firstStatement instanceof BSHPrimaryExpression ) 841 firstStatement = (SimpleNode)firstStatement.jjtGetChild(0); 842 if ( firstStatement instanceof BSHMethodInvocation ) 843 { 844 BSHMethodInvocation methodNode = 845 (BSHMethodInvocation)firstStatement; 846 BSHAmbiguousName methodName = methodNode.getNameNode(); 847 if ( methodName.text.equals("super") 848 || methodName.text.equals("this") 849 ) { 850 altConstructor = methodName.text; 851 argsNode = methodNode.getArgsNode(); 852 } 853 } 854 855 if ( altConstructor == null ) 856 return ConstructorArgs.DEFAULT; 858 NameSpace consArgsNameSpace = 861 new NameSpace( classStaticThis.getNameSpace(), "consArgs" ); 862 String [] consArgNames = constructor.getParameterNames(); 863 Class [] consArgTypes = constructor.getParameterTypes(); 864 for( int i=0; i<consArgs.length; i++ ) 865 { 866 try { 867 consArgsNameSpace.setTypedVariable( 868 consArgNames[i], consArgTypes[i], consArgs[i], 869 null); 870 } catch ( UtilEvalError e ) { 871 throw new InterpreterError("err setting local cons arg:"+e); 872 } 873 } 874 875 877 CallStack callstack = new CallStack(); 878 callstack.push( consArgsNameSpace); 879 Object [] args = null; 880 Interpreter interpreter = classStaticThis.declaringInterpreter; 881 882 try { 883 args = argsNode.getArguments( callstack, interpreter ); 884 } catch ( EvalError e ) { 885 throw new InterpreterError( 886 "Error evaluating constructor args: "+e ); 887 } 888 889 Class [] argTypes = Types.getTypes( args ); 890 args = Primitive.unwrap( args ); 891 Class superClass = 892 interpreter.getClassManager().classForName( superClassName ); 893 if ( superClass == null ) 894 throw new InterpreterError( 895 "can't find superclass: "+superClassName ); 896 Constructor [] superCons = superClass.getDeclaredConstructors(); 897 898 if ( altConstructor.equals("super") ) 900 { 901 int i = Reflect.findMostSpecificConstructorIndex( 902 argTypes , superCons ); 903 if ( i == -1 ) 904 throw new InterpreterError("can't find constructor for args!"); 905 return new ConstructorArgs( i, args ); 906 } 907 908 Class [][] candidates = new Class [ constructors.length ] []; 910 for(int i=0; i< candidates.length; i++ ) 911 candidates[i] = constructors[i].getParameterTypes(); 912 int i = Reflect.findMostSpecificSignature( argTypes, candidates ); 913 if ( i == -1 ) 914 throw new InterpreterError("can't find constructor for args 2!"); 915 917 int selector = i+superCons.length; 918 int ourSelector = index+superCons.length; 919 920 if ( selector == ourSelector ) 922 throw new InterpreterError( "Recusive constructor call."); 923 924 return new ConstructorArgs( selector, args ); 925 } 926 927 933 public static void initInstance( 934 Object instance, String className, Object [] args ) 935 { 936 Class [] sig = Types.getTypes( args ); 937 CallStack callstack = new CallStack(); 938 Interpreter interpreter; 939 NameSpace instanceNameSpace; 940 941 This instanceThis = getClassInstanceThis( instance, className ); 944 945 if ( instanceThis == null ) 947 { 948 951 This classStaticThis = 953 getClassStaticThis( instance.getClass(), className ); 954 interpreter = classStaticThis.declaringInterpreter; 955 956 BSHBlock instanceInitBlock; 958 try { 959 instanceInitBlock = (BSHBlock)classStaticThis.getNameSpace() 960 .getVariable( BSHINIT ); 961 } catch ( Exception e ) { 962 throw new InterpreterError( 963 "unable to get instance initializer: "+e ); 964 } 965 966 instanceNameSpace = 968 new NameSpace( classStaticThis.getNameSpace(), className ); 969 instanceNameSpace.isClass = true; 970 971 instanceThis = instanceNameSpace.getThis( interpreter ); 973 try { 974 LHS lhs = 975 Reflect.getLHSObjectField( instance, BSHTHIS+className ); 976 lhs.assign( instanceThis, false ); 977 } catch ( Exception e ) { 978 throw new InterpreterError("Error in class gen setup: "+e ); 979 } 980 981 instanceNameSpace.setClassInstance( instance ); 983 984 callstack.push( instanceNameSpace ); 986 987 try { instanceInitBlock.evalBlock( 990 callstack, interpreter, true, 991 ClassGeneratorImpl.ClassNodeFilter.CLASSINSTANCE ); 992 } catch ( Exception e ) { 993 throw new InterpreterError("Error in class initialization: "+e); 994 } 995 996 callstack.pop(); 997 998 } else 999 { 1000 interpreter = instanceThis.declaringInterpreter; 1003 instanceNameSpace = instanceThis.getNameSpace(); 1004 } 1005 1006 1008 String constructorName = getBaseName( className ); 1009 try { 1010 BshMethod constructor = instanceNameSpace.getMethod( 1012 constructorName, sig, true ); 1013 1014 if ( args.length > 0 && constructor == null ) 1016 throw new InterpreterError( 1017 "Can't find constructor: "+ className ); 1018 1019 if ( constructor != null ) 1021 constructor.invoke( args, interpreter, callstack, 1022 null, false ) ; 1023 } catch ( Exception e ) { 1024 if ( e instanceof TargetError ) 1025 e =(Exception )((TargetError)e).getTarget(); 1026 if ( e instanceof InvocationTargetException ) 1027 e = (Exception )((InvocationTargetException)e) 1028 .getTargetException(); 1029 e.printStackTrace( System.err ); 1030 throw new InterpreterError("Error in class initialization: "+e ); 1031 } 1032 } 1033 1034 1038 static This getClassStaticThis( Class clas, String className ) 1039 { 1040 try { 1041 return (This)Reflect.getStaticFieldValue( 1042 clas, BSHSTATIC + className ); 1043 } catch ( Exception e ) { 1044 throw new InterpreterError("Unable to get class static space: "+e); 1045 } 1046 } 1047 1048 1053 static This getClassInstanceThis( Object instance, String className ) 1054 { 1055 try { 1056 Object o = Reflect.getObjectFieldValue( instance, BSHTHIS+className ); 1057 return (This)Primitive.unwrap(o); } catch ( Exception e ) { 1059 throw new InterpreterError( 1060 "Generated class: Error getting This"+e ); 1061 } 1062 } 1063 1064 1067 private static boolean isPrimitive( String typeDescriptor ) 1068 { 1069 return typeDescriptor.length() == 1; } 1071 1072 static String [] getTypeDescriptors( Class [] cparams ) 1073 { 1074 String [] sa = new String [cparams.length]; 1075 for(int i=0; i<sa.length; i++) 1076 sa[i] = BSHType.getTypeDescriptor( cparams[i] ); 1077 return sa; 1078 } 1079 1080 1083 private static String descriptorToClassName( String s ) 1086 { 1087 if ( s.startsWith("[") || !s.startsWith("L") ) 1088 return s; 1089 return s.substring( 1, s.length()-1 ); 1090 } 1091 1092 private static String getBaseName( String className ) 1093 { 1094 int i = className.indexOf("$"); 1095 if ( i == -1 ) 1096 return className; 1097 1098 return className.substring(i+1); 1099 } 1100 1101 1107 public static class ConstructorArgs 1108 { 1109 1110 public static ConstructorArgs DEFAULT = new ConstructorArgs(); 1111 1112 public int selector = DEFAULTCONSTRUCTOR; 1113 Object [] args; 1114 int arg = 0; 1115 1118 1119 ConstructorArgs() { } 1120 1121 ConstructorArgs( int selector, Object [] args ) { 1122 this.selector = selector; 1123 this.args = args; 1124 } 1125 1126 Object next() { return args[arg++]; } 1127 1128 public boolean getBoolean() { return ((Boolean )next()).booleanValue(); } 1129 public byte getByte() { return ((Byte )next()).byteValue(); } 1130 public char getChar() { return ((Character )next()).charValue(); } 1131 public short getShort() { return ((Short )next()).shortValue(); } 1132 public int getInt() { return ((Integer )next()).intValue(); } 1133 public long getLong() { return ((Long )next()).longValue(); } 1134 public double getDouble() { return ((Double )next()).doubleValue(); } 1135 public float getFloat() { return ((Float )next()).floatValue(); } 1136 public Object getObject() { return next(); } 1137 } 1138} 1139 | Popular Tags |