src/jdk/internal/dynalink/beans/AbstractJavaLinker.java

changeset 101
f8221ce53c2e
parent 90
5a820fb11814
child 123
071e859b371e
equal deleted inserted replaced
100:3245e174fe3a 101:f8221ce53c2e
101 import jdk.internal.dynalink.linker.LinkerServices; 101 import jdk.internal.dynalink.linker.LinkerServices;
102 import jdk.internal.dynalink.support.CallSiteDescriptorFactory; 102 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
103 import jdk.internal.dynalink.support.Guards; 103 import jdk.internal.dynalink.support.Guards;
104 import jdk.internal.dynalink.support.Lookup; 104 import jdk.internal.dynalink.support.Lookup;
105 105
106
107 /** 106 /**
108 * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property 107 * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
109 * exposure and method calls for both static and instance facets of a class. 108 * exposure and method calls for both static and instance facets of a class.
110 * 109 *
111 * @author Attila Szegedi 110 * @author Attila Szegedi
126 this.clazz = clazz; 125 this.clazz = clazz;
127 this.classGuard = classGuard; 126 this.classGuard = classGuard;
128 this.assignableGuard = assignableGuard; 127 this.assignableGuard = assignableGuard;
129 128
130 final FacetIntrospector introspector = createFacetIntrospector(); 129 final FacetIntrospector introspector = createFacetIntrospector();
131 try { 130 // Add methods and properties
132 // Add methods and properties 131 for(Method method: introspector.getMethods()) {
133 for(Method method: introspector.getMethods()) { 132 final String name = method.getName();
134 final String name = method.getName(); 133 final MethodHandle methodHandle = introspector.unreflect(method);
135 final MethodHandle methodHandle = introspector.unreflect(method); 134 // Add method
136 // Add method 135 addMember(name, methodHandle, methods);
137 addMember(name, methodHandle, methods); 136 // Add the method as a property getter and/or setter
138 // Add the method as a property getter and/or setter 137 if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
139 if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) { 138 // Property getter
140 // Property getter 139 setPropertyGetter(Introspector.decapitalize(name.substring(3)), introspector.unreflect(
141 setPropertyGetter(Introspector.decapitalize(name.substring(3)), introspector.unreflect( 140 getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
142 getMostGenericGetter(method)), ValidationType.INSTANCE_OF); 141 } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
143 } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 && 142 method.getReturnType() == boolean.class) {
144 method.getReturnType() == boolean.class) { 143 // Boolean property getter
145 // Boolean property getter 144 setPropertyGetter(Introspector.decapitalize(name.substring(2)), introspector.unreflect(
146 setPropertyGetter(Introspector.decapitalize(name.substring(2)), introspector.unreflect( 145 getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
147 getMostGenericGetter(method)), ValidationType.INSTANCE_OF); 146 } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
148 } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) { 147 // Property setter
149 // Property setter 148 addMember(Introspector.decapitalize(name.substring(3)), methodHandle, propertySetters);
150 addMember(Introspector.decapitalize(name.substring(3)), methodHandle, propertySetters); 149 }
151 } 150 }
152 } 151
153 152 // Add field getter/setters as property getters/setters.
154 // Add field getter/setters as property getters/setters. 153 for(Field field: introspector.getFields()) {
155 for(Field field: introspector.getFields()) { 154 final String name = field.getName();
156 final String name = field.getName(); 155 // Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
157 // Only add a property getter when one is not defined already as a getXxx()/isXxx() method. 156 if(!propertyGetters.containsKey(name)) {
158 if(!propertyGetters.containsKey(name)) { 157 setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS);
159 setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS); 158 }
160 } 159 if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) {
161 if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) { 160 addMember(name, introspector.unreflectSetter(field), propertySetters);
162 addMember(name, introspector.unreflectSetter(field), propertySetters); 161 }
163 } 162 }
164 } 163
165 164 // Add inner classes, but only those for which we don't hide a property with it
166 // Add inner classes, but only those for which we don't hide a property with it 165 for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
167 for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) { 166 final String name = innerClassSpec.getKey();
168 final String name = innerClassSpec.getKey(); 167 if(!propertyGetters.containsKey(name)) {
169 if(!propertyGetters.containsKey(name)) { 168 setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
170 setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS); 169 }
171 }
172 }
173 } finally {
174 introspector.close();
175 } 170 }
176 } 171 }
177 172
178 abstract FacetIntrospector createFacetIntrospector(); 173 abstract FacetIntrospector createFacetIntrospector();
179 174
392 // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V)) 387 // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V))
393 final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( 388 final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
394 IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); 389 IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
395 if(nextComponent == null) { 390 if(nextComponent == null) {
396 return getClassGuardedInvocationComponent(compositeSetter, type); 391 return getClassGuardedInvocationComponent(compositeSetter, type);
397 } else { 392 }
398 return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, 393 return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
399 ValidationType.EXACT_CLASS);
400 }
401 } 394 }
402 case 3: { 395 case 3: {
403 // Must have two arguments: target object and property value 396 // Must have two arguments: target object and property value
404 assertParameterCount(callSiteDescriptor, 2); 397 assertParameterCount(callSiteDescriptor, 2);
405 final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor.getMethodType(), 398 final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor.getMethodType(),
472 // fold(R(AnnotatedMethodHandle, T0, T1), AnnotatedMethodHandle(T0, T1)) 465 // fold(R(AnnotatedMethodHandle, T0, T1), AnnotatedMethodHandle(T0, T1))
473 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( 466 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
474 IS_ANNOTATED_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); 467 IS_ANNOTATED_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
475 if(nextComponent == null) { 468 if(nextComponent == null) {
476 return getClassGuardedInvocationComponent(compositeGetter, type); 469 return getClassGuardedInvocationComponent(compositeGetter, type);
477 } else { 470 }
478 return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, 471 return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
479 ValidationType.EXACT_CLASS);
480 }
481 } 472 }
482 case 3: { 473 case 3: {
483 // Must have exactly one argument: receiver 474 // Must have exactly one argument: receiver
484 assertParameterCount(callSiteDescriptor, 1); 475 assertParameterCount(callSiteDescriptor, 1);
485 // Fixed name 476 // Fixed name
519 return Guards.isArray(0, methodType); 510 return Guards.isArray(0, methodType);
520 } 511 }
521 case NONE: { 512 case NONE: {
522 return null; 513 return null;
523 } 514 }
524 } 515 default: {
525 throw new AssertionError(); 516 throw new AssertionError();
517 }
518 }
526 } 519 }
527 520
528 private static final MethodHandle IS_DYNAMIC_METHOD_NOT_NULL = Guards.asType(Guards.isNotNull(), 521 private static final MethodHandle IS_DYNAMIC_METHOD_NOT_NULL = Guards.asType(Guards.isNotNull(),
529 MethodType.methodType(boolean.class, DynamicMethod.class)); 522 MethodType.methodType(boolean.class, DynamicMethod.class));
530 private static final MethodHandle DYNAMIC_METHOD_IDENTITY = MethodHandles.identity(DynamicMethod.class); 523 private static final MethodHandle DYNAMIC_METHOD_IDENTITY = MethodHandles.identity(DynamicMethod.class);
539 final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, 532 final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
540 linkerServices, ops); 533 linkerServices, ops);
541 if(nextComponent == null) { 534 if(nextComponent == null) {
542 // No next component operation; just return a component for this operation. 535 // No next component operation; just return a component for this operation.
543 return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type); 536 return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
544 } else { 537 }
545 // What's below is basically: 538
546 // foldArguments(guardWithTest(isNotNull, identity, nextComponent.invocation), getter) 539 // What's below is basically:
547 // only with a bunch of method signature adjustments. Basically, execute method getter; if 540 // foldArguments(guardWithTest(isNotNull, identity, nextComponent.invocation), getter) only with a
548 // it returns a non-null DynamicMethod, use identity to return it, otherwise delegate to 541 // bunch of method signature adjustments. Basically, execute method getter; if it returns a non-null
549 // nextComponent's invocation. 542 // DynamicMethod, use identity to return it, otherwise delegate to nextComponent's invocation.
550 543
551 final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType( 544 final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType(
552 DynamicMethod.class)); 545 DynamicMethod.class));
553 // Since it is part of the foldArgument() target, it will have extra args that we need to drop. 546 // Since it is part of the foldArgument() target, it will have extra args that we need to drop.
554 final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments( 547 final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
555 DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, 548 DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0,
556 DynamicMethod.class)); 549 DynamicMethod.class));
557 final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation(); 550 final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
558 // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly 551 // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly
559 assert nextComponentInvocation.type().equals(type); 552 assert nextComponentInvocation.type().equals(type);
560 // Since it is part of the foldArgument() target, we have to drop an extra arg it receives. 553 // Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
561 final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0, 554 final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
562 DynamicMethod.class); 555 DynamicMethod.class);
563 // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get) 556 // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
564 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( 557 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
565 IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter); 558 IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter);
566 559
567 return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, 560 return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
568 ValidationType.EXACT_CLASS);
569 }
570 } 561 }
571 case 3: { 562 case 3: {
572 // Must have exactly one argument: receiver 563 // Must have exactly one argument: receiver
573 assertParameterCount(callSiteDescriptor, 1); 564 assertParameterCount(callSiteDescriptor, 1);
574 final DynamicMethod method = getDynamicMethod(callSiteDescriptor.getNameToken( 565 final DynamicMethod method = getDynamicMethod(callSiteDescriptor.getNameToken(
636 * 627 *
637 * @param name name of the method 628 * @param name name of the method
638 * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the 629 * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the
639 * method with the specified name does not exist. 630 * method with the specified name does not exist.
640 */ 631 */
641 public DynamicMethod getDynamicMethod(String name) { 632 DynamicMethod getDynamicMethod(String name) {
642 return getDynamicMethod(name, methods); 633 return getDynamicMethod(name, methods);
643 } 634 }
644 635
645 /** 636 /**
646 * Find the most generic superclass that declares this getter. Since getters have zero args (aside from the 637 * Find the most generic superclass that declares this getter. Since getters have zero args (aside from the

mercurial