001/*
002 * Copyright 2002-2012 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.mock.web;
018
019import javax.servlet.RequestDispatcher;
020import javax.servlet.ServletRequest;
021import javax.servlet.ServletResponse;
022import javax.servlet.http.HttpServletResponseWrapper;
023
024import org.apache.commons.logging.Log;
025import org.apache.commons.logging.LogFactory;
026
027import org.springframework.util.Assert;
028
029/**
030 * Mock implementation of the {@link javax.servlet.RequestDispatcher} interface.
031 *
032 * <p>Used for testing the web framework; typically not necessary for
033 * testing application controllers.
034 *
035 * @author Rod Johnson
036 * @author Juergen Hoeller
037 * @author Sam Brannen
038 * @since 1.0.2
039 */
040public class MockRequestDispatcher implements RequestDispatcher {
041
042        private final Log logger = LogFactory.getLog(getClass());
043
044        private final String resource;
045
046
047        /**
048         * Create a new MockRequestDispatcher for the given resource.
049         * @param resource the server resource to dispatch to, located at a
050         * particular path or given by a particular name
051         */
052        public MockRequestDispatcher(String resource) {
053                Assert.notNull(resource, "resource must not be null");
054                this.resource = resource;
055        }
056
057
058        @Override
059        public void forward(ServletRequest request, ServletResponse response) {
060                Assert.notNull(request, "Request must not be null");
061                Assert.notNull(response, "Response must not be null");
062                if (response.isCommitted()) {
063                        throw new IllegalStateException("Cannot perform forward - response is already committed");
064                }
065                getMockHttpServletResponse(response).setForwardedUrl(this.resource);
066                if (logger.isDebugEnabled()) {
067                        logger.debug("MockRequestDispatcher: forwarding to [" + this.resource + "]");
068                }
069        }
070
071        @Override
072        public void include(ServletRequest request, ServletResponse response) {
073                Assert.notNull(request, "Request must not be null");
074                Assert.notNull(response, "Response must not be null");
075                getMockHttpServletResponse(response).addIncludedUrl(this.resource);
076                if (logger.isDebugEnabled()) {
077                        logger.debug("MockRequestDispatcher: including [" + this.resource + "]");
078                }
079        }
080
081        /**
082         * Obtain the underlying {@link MockHttpServletResponse}, unwrapping
083         * {@link HttpServletResponseWrapper} decorators if necessary.
084         */
085        protected MockHttpServletResponse getMockHttpServletResponse(ServletResponse response) {
086                if (response instanceof MockHttpServletResponse) {
087                        return (MockHttpServletResponse) response;
088                }
089                if (response instanceof HttpServletResponseWrapper) {
090                        return getMockHttpServletResponse(((HttpServletResponseWrapper) response).getResponse());
091                }
092                throw new IllegalArgumentException("MockRequestDispatcher requires MockHttpServletResponse");
093        }
094
095}