@@ -438,50 +438,71 @@ public static RubyModule getProxyClass(Ruby runtime, JavaClass javaClass) {
438
438
}
439
439
440
440
public static RubyModule getProxyClass (final Ruby runtime , final Class <?> clazz ) {
441
- RubyModule unfinished = runtime .getJavaSupport ().getUnfinishedProxyClassCache (). get ( clazz ). get ( );
442
- if (unfinished != null ) return unfinished ;
441
+ RubyModule proxy = runtime .getJavaSupport ().getUnfinishedProxy ( clazz );
442
+ if (proxy != null ) return proxy ;
443
443
return runtime .getJavaSupport ().getProxyClassFromCache (clazz );
444
444
}
445
445
446
446
// Only used by proxy ClassValue calculator in JavaSupport
447
447
static RubyModule createProxyClassForClass (final Ruby runtime , final Class <?> clazz ) {
448
448
final JavaSupport javaSupport = runtime .getJavaSupport ();
449
449
450
- if (clazz .isInterface ()) return generateInterfaceProxy (runtime , clazz );
451
-
452
- return generateClassProxy (runtime , clazz , javaSupport );
453
- }
450
+ RubyModule proxy ;
451
+ RubyClass superClass = null ;
452
+ if (clazz .isInterface ()) {
453
+ proxy = (RubyModule ) runtime .getJavaSupport ().getJavaInterfaceTemplate ().dup ();
454
+ } else {
455
+ if (clazz .isArray ()) {
456
+ superClass = javaSupport .getArrayProxyClass ();
457
+ } else if (clazz .isPrimitive ()) {
458
+ superClass = javaSupport .getConcreteProxyClass ();
459
+ } else if (clazz == Object .class ) {
460
+ superClass = javaSupport .getConcreteProxyClass ();
461
+ } else {
462
+ // other java proxy classes added under their superclass' java proxy
463
+ superClass = (RubyClass ) getProxyClass (runtime , clazz .getSuperclass ());
464
+ }
465
+ proxy = RubyClass .newClass (runtime , superClass );
466
+ }
454
467
455
- private static RubyModule generateInterfaceProxy (final Ruby runtime , final Class javaClass ) {
456
- if (!javaClass .isInterface ()) {
457
- throw runtime .newArgumentError (javaClass .toString () + " is not an interface" );
468
+ // ensure proxy is visible down-thread
469
+ javaSupport .beginProxy (clazz , proxy );
470
+ try {
471
+ if (clazz .isInterface ()) {
472
+ generateInterfaceProxy (runtime , clazz , proxy );
473
+ } else {
474
+ generateClassProxy (runtime , clazz , (RubyClass )proxy , superClass , javaSupport );
475
+ }
476
+ } finally {
477
+ javaSupport .endProxy (clazz );
458
478
}
459
479
460
- RubyModule proxyModule = (RubyModule ) runtime .getJavaSupport ().getJavaInterfaceTemplate ().dup ();
480
+ return proxy ;
481
+ }
482
+
483
+ private static void generateInterfaceProxy (final Ruby runtime , final Class javaClass , final RubyModule proxy ) {
484
+ assert javaClass .isInterface () : "not an interface: " + javaClass ;
461
485
462
486
// include any interfaces we extend
463
487
final Class <?>[] extended = javaClass .getInterfaces ();
464
- for ( int i = extended .length ; --i >= 0 ; ) {
488
+ for (int i = extended .length ; --i >= 0 ; ) {
465
489
RubyModule extModule = getInterfaceModule (runtime , extended [i ]);
466
- proxyModule .includeModule (extModule );
490
+ proxy .includeModule (extModule );
467
491
}
468
- Initializer .setupProxyModule (runtime , javaClass , proxyModule );
469
- addToJavaPackageModule (proxyModule );
470
-
471
- return proxyModule ;
492
+ Initializer .setupProxyModule (runtime , javaClass , proxy );
493
+ addToJavaPackageModule (proxy );
472
494
}
473
495
474
- private static RubyModule generateClassProxy (Ruby runtime , Class <?> clazz , JavaSupport javaSupport ) {
475
- RubyModule proxyClass ;
496
+ private static void generateClassProxy (Ruby runtime , Class <?> clazz , RubyClass proxy , RubyClass superClass , JavaSupport javaSupport ) {
476
497
if (clazz .isArray ()) {
477
- proxyClass = createProxyClass (runtime , javaSupport . getArrayProxyClass () , clazz , true );
498
+ createProxyClass (runtime , proxy , clazz , true );
478
499
479
500
// FIXME: Organizationally this might be nicer in a specialized class
480
501
if ( clazz .getComponentType () == byte .class ) {
481
502
final Encoding ascii8bit = runtime .getEncodingService ().getAscii8bitEncoding ();
482
503
483
504
// All bytes can be considered raw strings and forced to particular codings if not 8bitascii
484
- proxyClass .addMethod ("to_s" , new JavaMethodZero (proxyClass , PUBLIC ) {
505
+ proxy .addMethod ("to_s" , new JavaMethodZero (proxy , PUBLIC ) {
485
506
@ Override
486
507
public IRubyObject call (ThreadContext context , IRubyObject self , RubyModule clazz , String name ) {
487
508
ByteList bytes = new ByteList ((byte []) ((ArrayJavaProxy ) self ).getObject (), ascii8bit );
@@ -491,55 +512,48 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
491
512
}
492
513
}
493
514
else if ( clazz .isPrimitive () ) {
494
- proxyClass = createProxyClass (runtime , javaSupport . getConcreteProxyClass () , clazz , true );
515
+ createProxyClass (runtime , proxy , clazz , true );
495
516
}
496
517
else if ( clazz == Object .class ) {
497
518
// java.lang.Object is added at root of java proxy classes
498
- proxyClass = createProxyClass (runtime , javaSupport . getConcreteProxyClass () , clazz , true );
519
+ createProxyClass (runtime , proxy , clazz , true );
499
520
if (NEW_STYLE_EXTENSION ) {
500
- proxyClass .getMetaClass ().defineAnnotatedMethods (NewStyleExtensionInherited .class );
521
+ proxy .getMetaClass ().defineAnnotatedMethods (NewStyleExtensionInherited .class );
501
522
} else {
502
- proxyClass .getMetaClass ().defineAnnotatedMethods (OldStyleExtensionInherited .class );
523
+ proxy .getMetaClass ().defineAnnotatedMethods (OldStyleExtensionInherited .class );
503
524
}
504
- addToJavaPackageModule (proxyClass );
525
+ addToJavaPackageModule (proxy );
505
526
}
506
527
else {
507
- // other java proxy classes added under their superclass' java proxy
508
- RubyClass superProxyClass = (RubyClass ) getProxyClass (runtime , clazz .getSuperclass ());
509
- proxyClass = createProxyClass (runtime , superProxyClass , clazz , false );
528
+ createProxyClass (runtime , proxy , clazz , false );
510
529
// include interface modules into the proxy class
511
530
final Class <?>[] interfaces = clazz .getInterfaces ();
512
531
for ( int i = interfaces .length ; --i >= 0 ; ) {
513
- proxyClass .includeModule (getInterfaceModule (runtime , interfaces [i ]));
532
+ proxy .includeModule (getInterfaceModule (runtime , interfaces [i ]));
514
533
}
515
534
if ( Modifier .isPublic (clazz .getModifiers ()) ) {
516
- addToJavaPackageModule (proxyClass );
535
+ addToJavaPackageModule (proxy );
517
536
}
518
537
}
519
538
520
539
// JRUBY-1000, fail early when attempting to subclass a final Java class;
521
540
// solved here by adding an exception-throwing "inherited"
522
541
if ( Modifier .isFinal (clazz .getModifiers ()) ) {
523
542
final String clazzName = clazz .getCanonicalName ();
524
- proxyClass .getMetaClass ().addMethod ("inherited" , new org .jruby .internal .runtime .methods .JavaMethod (proxyClass , PUBLIC ) {
543
+ proxy .getMetaClass ().addMethod ("inherited" , new org .jruby .internal .runtime .methods .JavaMethod (proxy , PUBLIC ) {
525
544
@ Override
526
545
public IRubyObject call (ThreadContext context , IRubyObject self , RubyModule clazz , String name , IRubyObject [] args , Block block ) {
527
546
throw context .runtime .newTypeError ("can not extend final Java class: " + clazzName );
528
547
}
529
548
});
530
549
}
531
-
532
- return proxyClass ;
533
550
}
534
551
535
552
private static RubyClass createProxyClass (final Ruby runtime ,
536
- final RubyClass baseType , final Class <?> javaClass , boolean invokeInherited ) {
537
- RubyClass proxyClass ;
553
+ final RubyClass proxyClass , final Class <?> javaClass , boolean invokeInherited ) {
538
554
539
- // this needs to be split, since conditional calling #inherited doesn't fit standard ruby semantics
555
+ final RubyClass superClass = proxyClass . getSuperClass ();
540
556
541
- final RubyClass superClass = baseType ;
542
- proxyClass = RubyClass .newClass (runtime , superClass );
543
557
proxyClass .makeMetaClass ( superClass .getMetaClass () );
544
558
545
559
if ( Map .class .isAssignableFrom ( javaClass ) ) {
@@ -1456,6 +1470,6 @@ private static void addToJavaPackageModule(RubyModule proxyClass, JavaClass java
1456
1470
@ Deprecated
1457
1471
private static RubyClass createProxyClass (final Ruby runtime ,
1458
1472
final RubyClass baseType , final JavaClass javaClass , boolean invokeInherited ) {
1459
- return createProxyClass (runtime , baseType , javaClass . javaClass () , invokeInherited );
1473
+ return createProxyClass (runtime , RubyClass . newClass ( runtime , baseType ) , javaClass , invokeInherited );
1460
1474
}
1461
1475
}
0 commit comments