001/* 002 * Copyright 2002-2020 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.messaging.handler.invocation.reactive; 018 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.List; 022 023import org.apache.commons.logging.Log; 024import org.apache.commons.logging.LogFactory; 025import reactor.core.publisher.Mono; 026 027import org.springframework.core.MethodParameter; 028import org.springframework.lang.Nullable; 029import org.springframework.messaging.Message; 030 031/** 032 * A HandlerMethodReturnValueHandler that wraps and delegates to others. 033 * 034 * @author Rossen Stoyanchev 035 * @since 5.2 036 */ 037public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler { 038 039 protected final Log logger = LogFactory.getLog(getClass()); 040 041 private final List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<>(); 042 043 044 /** 045 * Return a read-only list with the configured handlers. 046 */ 047 public List<HandlerMethodReturnValueHandler> getReturnValueHandlers() { 048 return Collections.unmodifiableList(this.returnValueHandlers); 049 } 050 051 /** 052 * Clear the list of configured handlers. 053 */ 054 public void clear() { 055 this.returnValueHandlers.clear(); 056 } 057 058 /** 059 * Add the given {@link HandlerMethodReturnValueHandler}. 060 */ 061 public HandlerMethodReturnValueHandlerComposite addHandler(HandlerMethodReturnValueHandler returnValueHandler) { 062 this.returnValueHandlers.add(returnValueHandler); 063 return this; 064 } 065 066 /** 067 * Add the given {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers}. 068 */ 069 public HandlerMethodReturnValueHandlerComposite addHandlers( 070 @Nullable List<? extends HandlerMethodReturnValueHandler> handlers) { 071 072 if (handlers != null) { 073 this.returnValueHandlers.addAll(handlers); 074 } 075 return this; 076 } 077 078 @Override 079 public boolean supportsReturnType(MethodParameter returnType) { 080 return getReturnValueHandler(returnType) != null; 081 } 082 083 @Override 084 public Mono<Void> handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, Message<?> message) { 085 HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType); 086 if (handler == null) { 087 throw new IllegalStateException("No handler for return value type: " + returnType.getParameterType()); 088 } 089 if (logger.isTraceEnabled()) { 090 logger.trace("Processing return value with " + handler); 091 } 092 return handler.handleReturnValue(returnValue, returnType, message); 093 } 094 095 @SuppressWarnings("ForLoopReplaceableByForEach") 096 @Nullable 097 private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) { 098 for (int i = 0; i < this.returnValueHandlers.size(); i++) { 099 HandlerMethodReturnValueHandler handler = this.returnValueHandlers.get(i); 100 if (handler.supportsReturnType(returnType)) { 101 return handler; 102 } 103 } 104 return null; 105 } 106 107}