@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( MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { returnType.increaseNestingLevel(); Type nestedType = returnType.getNestedGenericParameterType(); returnType.decreaseNestingLevel(); return ResourceSupport.class.isAssignableFrom(returnType.getParameterType()) || TypeUtils.isAssignable(ResourceSupport.class, nestedType); }
@Override public Mono<Object> resolveArgument( MethodParameter param, BindingContext bindingContext, ServerWebExchange exchange) { ResolvableType entityType = ResolvableType.forMethodParameter(param); MethodParameter bodyParameter = new MethodParameter(param); bodyParameter.increaseNestingLevel(); return readBody(bodyParameter, false, bindingContext, exchange) .map(body -> createHttpEntity(body, entityType, exchange)) .defaultIfEmpty(createHttpEntity(null, entityType, exchange)); }
private synchronized void setExclusiveTargetParameterType( TypeDescriptor targetParameterType, MethodParameter methodParameter) { if (this.targetParameterTypeDescriptor != null) { throw new IneligibleMethodException( "Found more than one parameter type candidate: [" + this.targetParameterTypeDescriptor + "] and [" + targetParameterType + "]"); } this.targetParameterTypeDescriptor = targetParameterType; if (Message.class.isAssignableFrom(targetParameterType.getObjectType())) { methodParameter.increaseNestingLevel(); this.targetParameterType = methodParameter.getNestedParameterType(); methodParameter.decreaseNestingLevel(); } else { this.targetParameterType = targetParameterType.getObjectType(); } }
@SuppressWarnings("unchecked") protected Map convertToTypedMap( Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) { boolean originalAllowed = requiredType.isInstance(original); if (!originalAllowed && !Map.class.isAssignableFrom(requiredType)) { return original; } Class keyType = null; Class valueType = null; MethodParameter methodParam = typeDescriptor.getMethodParameter(); if (methodParam != null) { keyType = GenericCollectionTypeResolver.getMapKeyParameterType(methodParam); valueType = GenericCollectionTypeResolver.getMapValueParameterType(methodParam); } if (keyType == null && valueType == null && originalAllowed && !this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) { return original; } Iterator it; try { it = original.entrySet().iterator(); if (it == null) { if (logger.isDebugEnabled()) { logger.debug( "Map of type [" + original.getClass().getName() + "] returned null Iterator - injecting original Map as-is"); } return original; } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Cannot access Map of type [" + original.getClass().getName() + "] - injecting original Map as-is", ex); } return original; } Map convertedCopy; try { if (CollectionFactory.isApproximableMapType(requiredType)) { convertedCopy = CollectionFactory.createApproximateMap(original, original.size()); } else { convertedCopy = (Map) requiredType.newInstance(); } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Cannot create copy of Map type [" + original.getClass().getName() + "] - injecting original Map as-is", ex); } return original; } while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); Object key = entry.getKey(); Object value = entry.getValue(); String keyedPropertyName = buildKeyedPropertyName(propertyName, key); if (methodParam != null) { methodParam.increaseNestingLevel(); methodParam.setTypeIndexForCurrentLevel(0); } Object convertedKey = convertIfNecessary(keyedPropertyName, null, key, keyType, typeDescriptor); if (methodParam != null) { methodParam.setTypeIndexForCurrentLevel(1); } Object convertedValue = convertIfNecessary(keyedPropertyName, null, value, valueType, typeDescriptor); if (methodParam != null) { methodParam.decreaseNestingLevel(); } try { convertedCopy.put(convertedKey, convertedValue); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Map type [" + original.getClass().getName() + "] seems to be read-only - injecting original Map as-is", ex); } return original; } originalAllowed = originalAllowed && (key == convertedKey) && (value == convertedValue); } return (originalAllowed ? original : convertedCopy); }
@SuppressWarnings("unchecked") protected Collection convertToTypedCollection( Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) { boolean originalAllowed = requiredType.isInstance(original); if (!originalAllowed && !Collection.class.isAssignableFrom(requiredType)) { return original; } MethodParameter methodParam = typeDescriptor.getMethodParameter(); Class elementType = null; if (methodParam != null) { elementType = GenericCollectionTypeResolver.getCollectionParameterType(methodParam); } if (elementType == null && originalAllowed && !this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) { return original; } Iterator it; try { it = original.iterator(); if (it == null) { if (logger.isDebugEnabled()) { logger.debug( "Collection of type [" + original.getClass().getName() + "] returned null Iterator - injecting original Collection as-is"); } return original; } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Cannot access Collection of type [" + original.getClass().getName() + "] - injecting original Collection as-is", ex); } return original; } Collection convertedCopy; try { if (CollectionFactory.isApproximableCollectionType(requiredType)) { convertedCopy = CollectionFactory.createApproximateCollection(original, original.size()); } else { convertedCopy = (Collection) requiredType.newInstance(); } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Cannot create copy of Collection type [" + original.getClass().getName() + "] - injecting original Collection as-is", ex); } return original; } int i = 0; for (; it.hasNext(); i++) { Object element = it.next(); String indexedPropertyName = buildIndexedPropertyName(propertyName, i); if (methodParam != null) { methodParam.increaseNestingLevel(); } Object convertedElement = convertIfNecessary(indexedPropertyName, null, element, elementType, typeDescriptor); if (methodParam != null) { methodParam.decreaseNestingLevel(); } try { convertedCopy.add(convertedElement); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Collection type [" + original.getClass().getName() + "] seems to be read-only - injecting original Collection as-is", ex); } return original; } originalAllowed = originalAllowed && (element == convertedElement); } return (originalAllowed ? original : convertedCopy); }