001/* 002 * Copyright 2002-2014 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; 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; 025 026import org.springframework.core.MethodParameter; 027import org.springframework.messaging.Message; 028import org.springframework.util.Assert; 029import org.springframework.util.concurrent.ListenableFuture; 030 031/** 032 * A HandlerMethodReturnValueHandler that wraps and delegates to others. 033 * 034 * @author Rossen Stoyanchev 035 * @since 4.0 036 */ 037public class HandlerMethodReturnValueHandlerComposite implements AsyncHandlerMethodReturnValueHandler { 038 039 private static final Log logger = LogFactory.getLog(HandlerMethodReturnValueHandlerComposite.class); 040 041 private final List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<HandlerMethodReturnValueHandler>(); 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}s. 068 */ 069 public HandlerMethodReturnValueHandlerComposite addHandlers(List<? extends HandlerMethodReturnValueHandler> handlers) { 070 if (handlers != null) { 071 for (HandlerMethodReturnValueHandler handler : handlers) { 072 this.returnValueHandlers.add(handler); 073 } 074 } 075 return this; 076 } 077 078 @Override 079 public boolean supportsReturnType(MethodParameter returnType) { 080 return getReturnValueHandler(returnType) != null; 081 } 082 083 private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) { 084 for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { 085 if (handler.supportsReturnType(returnType)) { 086 return handler; 087 } 088 } 089 return null; 090 } 091 092 @Override 093 public void handleReturnValue(Object returnValue, MethodParameter returnType, Message<?> message) 094 throws Exception { 095 096 HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType); 097 if (handler == null) { 098 throw new IllegalStateException("No handler for return value type: " + returnType.getParameterType()); 099 } 100 if (logger.isTraceEnabled()) { 101 logger.trace("Processing return value with " + handler); 102 } 103 handler.handleReturnValue(returnValue, returnType, message); 104 } 105 106 @Override 107 public boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType) { 108 HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType); 109 return (handler instanceof AsyncHandlerMethodReturnValueHandler && 110 ((AsyncHandlerMethodReturnValueHandler) handler).isAsyncReturnValue(returnValue, returnType)); 111 } 112 113 @Override 114 public ListenableFuture<?> toListenableFuture(Object returnValue, MethodParameter returnType) { 115 HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType); 116 Assert.state(handler instanceof AsyncHandlerMethodReturnValueHandler, 117 "AsyncHandlerMethodReturnValueHandler required"); 118 return ((AsyncHandlerMethodReturnValueHandler) handler).toListenableFuture(returnValue, returnType); 119 } 120 121}