001/*
002 * Copyright 2002-2019 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.web.servlet.function.support;
018
019import java.util.List;
020
021import javax.servlet.http.HttpServletRequest;
022import javax.servlet.http.HttpServletResponse;
023
024import org.springframework.core.Ordered;
025import org.springframework.http.converter.HttpMessageConverter;
026import org.springframework.lang.Nullable;
027import org.springframework.util.Assert;
028import org.springframework.web.servlet.HandlerAdapter;
029import org.springframework.web.servlet.ModelAndView;
030import org.springframework.web.servlet.function.HandlerFunction;
031import org.springframework.web.servlet.function.RouterFunctions;
032import org.springframework.web.servlet.function.ServerRequest;
033import org.springframework.web.servlet.function.ServerResponse;
034
035/**
036 * {@code HandlerAdapter} implementation that supports {@link HandlerFunction}s.
037 *
038 * @author Arjen Poutsma
039 * @since 5.2
040 */
041public class HandlerFunctionAdapter implements HandlerAdapter, Ordered {
042
043        private int order = Ordered.LOWEST_PRECEDENCE;
044
045
046        /**
047         * Specify the order value for this HandlerAdapter bean.
048         * <p>The default value is {@code Ordered.LOWEST_PRECEDENCE}, meaning non-ordered.
049         * @see org.springframework.core.Ordered#getOrder()
050         */
051        public void setOrder(int order) {
052                this.order = order;
053        }
054
055        @Override
056        public int getOrder() {
057                return this.order;
058        }
059
060        @Override
061        public boolean supports(Object handler) {
062                return handler instanceof HandlerFunction;
063        }
064
065        @Nullable
066        @Override
067        public ModelAndView handle(HttpServletRequest servletRequest,
068                        HttpServletResponse servletResponse,
069                        Object handler) throws Exception {
070
071
072                HandlerFunction<?> handlerFunction = (HandlerFunction<?>) handler;
073
074                ServerRequest serverRequest = getServerRequest(servletRequest);
075                ServerResponse serverResponse = handlerFunction.handle(serverRequest);
076
077                return serverResponse.writeTo(servletRequest, servletResponse,
078                                new ServerRequestContext(serverRequest));
079        }
080
081        private ServerRequest getServerRequest(HttpServletRequest servletRequest) {
082                ServerRequest serverRequest =
083                                (ServerRequest) servletRequest.getAttribute(RouterFunctions.REQUEST_ATTRIBUTE);
084                Assert.state(serverRequest != null, () -> "Required attribute '" +
085                                RouterFunctions.REQUEST_ATTRIBUTE + "' is missing");
086                return serverRequest;
087        }
088
089        @Override
090        public long getLastModified(HttpServletRequest request, Object handler) {
091                return -1L;
092        }
093
094
095        private static class ServerRequestContext implements ServerResponse.Context {
096
097                private final ServerRequest serverRequest;
098
099
100                public ServerRequestContext(ServerRequest serverRequest) {
101                        this.serverRequest = serverRequest;
102                }
103
104                @Override
105                public List<HttpMessageConverter<?>> messageConverters() {
106                        return this.serverRequest.messageConverters();
107                }
108        }
109}