/** * Invokes all {@link ResourceProcessor} instances registered for the type of the given value and * reference type. * * @param value must not be {@literal null}. * @param referenceType must not be {@literal null}. * @return */ @SuppressWarnings("unchecked") public <T extends ResourceSupport> T invokeProcessorsFor(T value, ResolvableType referenceType) { Assert.notNull(value, "Value must not be null!"); Assert.notNull(referenceType, "Reference type must not be null!"); // For Resources implementations, process elements first if (ResourceProcessorHandlerMethodReturnValueHandler.RESOURCES_TYPE.isAssignableFrom( referenceType)) { Resources<?> resources = (Resources<?>) value; ResolvableType elementTargetType = ResolvableType.forClass(Resources.class, referenceType.getRawClass()).getGeneric(0); List<Object> result = new ArrayList<Object>(resources.getContent().size()); for (Object element : resources) { ResolvableType elementType = ResolvableType.forClass(element.getClass()); if (!getRawType(elementTargetType).equals(elementType.getRawClass())) { elementTargetType = elementType; } result.add(invokeProcessorsFor(element, elementTargetType)); } ReflectionUtils.setField( ResourceProcessorHandlerMethodReturnValueHandler.CONTENT_FIELD, resources, result); } return (T) invokeProcessorsFor((Object) value, referenceType); }
@Override public boolean supportsEventType(ResolvableType resolvableType) { Class<?> type = resolvableType.getRawClass(); if (type == null) { return false; } return ApplicationStartedEvent.class.isAssignableFrom(type) || ApplicationFailedEvent.class.isAssignableFrom(type); }
private Object createHttpEntity( Object body, ResolvableType entityType, ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); if (RequestEntity.class == entityType.getRawClass()) { return new RequestEntity<>(body, headers, request.getMethod(), request.getURI()); } else { return new HttpEntity<>(body, headers); } }
private ResolvableType getResolvableType(ApplicationEvent event) { ResolvableType payloadType = null; if (event instanceof PayloadApplicationEvent) { PayloadApplicationEvent<?> payloadEvent = (PayloadApplicationEvent<?>) event; payloadType = payloadEvent.getResolvableType().as(PayloadApplicationEvent.class).getGeneric(0); } for (ResolvableType declaredEventType : this.declaredEventTypes) { if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) && payloadType != null) { if (declaredEventType.isAssignableFrom(payloadType)) { return declaredEventType; } } if (declaredEventType.getRawClass().isAssignableFrom(event.getClass())) { return declaredEventType; } } return null; }
@Override public boolean supportsEventType(ResolvableType eventType) { for (ResolvableType declaredEventType : this.declaredEventTypes) { if (declaredEventType.isAssignableFrom(eventType)) { return true; } else if (PayloadApplicationEvent.class.isAssignableFrom(eventType.getRawClass())) { ResolvableType payloadType = eventType.as(PayloadApplicationEvent.class).getGeneric(); if (declaredEventType.isAssignableFrom(payloadType)) { return true; } } } return eventType.hasUnresolvableGenerics(); }
/** * Resolve the method arguments to use for the specified {@link ApplicationEvent}. * * <p>These arguments will be used to invoke the method handled by this instance. Can return * {@code null} to indicate that no suitable arguments could be resolved and therefore the method * should not be invoked at all for the specified event. */ protected Object[] resolveArguments(ApplicationEvent event) { ResolvableType declaredEventType = getResolvableType(event); if (declaredEventType == null) { return null; } if (this.method.getParameterCount() == 0) { return new Object[0]; } if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) && event instanceof PayloadApplicationEvent) { return new Object[] {((PayloadApplicationEvent) event).getPayload()}; } else { return new Object[] {event}; } }
@Override public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) { ResolvableType returnType = result.getReturnType(); MethodParameter bodyType; Mono<?> returnValueMono; Optional<Object> optionalValue = result.getReturnValue(); Class<?> rawClass = returnType.getRawClass(); ReactiveAdapter adapter = getAdapterRegistry().getAdapterFrom(rawClass, optionalValue); if (adapter != null) { returnValueMono = adapter.toMono(optionalValue); bodyType = new MethodParameter(result.getReturnTypeSource()); bodyType.increaseNestingLevel(); bodyType.increaseNestingLevel(); } else { returnValueMono = Mono.justOrEmpty(optionalValue); bodyType = new MethodParameter(result.getReturnTypeSource()); bodyType.increaseNestingLevel(); } return returnValueMono.then( returnValue -> { Assert.isInstanceOf(HttpEntity.class, returnValue); HttpEntity<?> httpEntity = (HttpEntity<?>) returnValue; if (httpEntity instanceof ResponseEntity) { ResponseEntity<?> responseEntity = (ResponseEntity<?>) httpEntity; exchange.getResponse().setStatusCode(responseEntity.getStatusCode()); } HttpHeaders entityHeaders = httpEntity.getHeaders(); HttpHeaders responseHeaders = exchange.getResponse().getHeaders(); if (!entityHeaders.isEmpty()) { entityHeaders .entrySet() .stream() .filter(entry -> !responseHeaders.containsKey(entry.getKey())) .forEach(entry -> responseHeaders.put(entry.getKey(), entry.getValue())); } return writeBody(httpEntity.getBody(), bodyType, exchange); }); }
@Override public boolean supports(HandlerResult result) { Class<?> returnType = result.getReturnType().getRawClass(); if (isSupportedType(returnType)) { return true; } else { ReactiveAdapter adapter = getAdapterRegistry().getAdapterFrom(returnType, result.getReturnValue()); if (adapter != null && !adapter.getDescriptor().isMultiValue() && !adapter.getDescriptor().isNoValue()) { ResolvableType genericType = result.getReturnType().getGeneric(0); return isSupportedType(genericType.getRawClass()); } } return false; }
private static Class<?> getRawType(ResolvableType type) { Class<?> rawType = type.getRawClass(); return rawType == null ? Object.class : rawType; }
@Override public boolean canEncode(ResolvableType elementType, MimeType mimeType, Object... hints) { Class<?> clazz = elementType.getRawClass(); return (super.canEncode(elementType, mimeType, hints) && Resource.class.isAssignableFrom(clazz)); }