001/*
002 * Copyright 2002-2016 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.test.web.servlet.request;
018
019import java.net.URI;
020import java.util.ArrayList;
021import java.util.List;
022import javax.servlet.ServletContext;
023
024import org.springframework.http.HttpMethod;
025import org.springframework.http.MediaType;
026import org.springframework.mock.web.MockHttpServletRequest;
027import org.springframework.mock.web.MockMultipartFile;
028import org.springframework.mock.web.MockMultipartHttpServletRequest;
029
030/**
031 * Default builder for {@link MockMultipartHttpServletRequest}.
032 *
033 * @author Rossen Stoyanchev
034 * @author Arjen Poutsma
035 * @since 3.2
036 */
037public class MockMultipartHttpServletRequestBuilder extends MockHttpServletRequestBuilder {
038
039        private final List<MockMultipartFile> files = new ArrayList<MockMultipartFile>();
040
041
042        /**
043         * Package-private constructor. Use static factory methods in
044         * {@link MockMvcRequestBuilders}.
045         * <p>For other ways to initialize a {@code MockMultipartHttpServletRequest},
046         * see {@link #with(RequestPostProcessor)} and the
047         * {@link RequestPostProcessor} extension point.
048         * @param urlTemplate a URL template; the resulting URL will be encoded
049         * @param uriVariables zero or more URI variables
050         */
051        MockMultipartHttpServletRequestBuilder(String urlTemplate, Object... uriVariables) {
052                super(HttpMethod.POST, urlTemplate, uriVariables);
053                super.contentType(MediaType.MULTIPART_FORM_DATA);
054        }
055
056        /**
057         * Package-private constructor. Use static factory methods in
058         * {@link MockMvcRequestBuilders}.
059         * <p>For other ways to initialize a {@code MockMultipartHttpServletRequest},
060         * see {@link #with(RequestPostProcessor)} and the
061         * {@link RequestPostProcessor} extension point.
062         * @param uri the URL
063         * @since 4.0.3
064         */
065        MockMultipartHttpServletRequestBuilder(URI uri) {
066                super(HttpMethod.POST, uri);
067                super.contentType(MediaType.MULTIPART_FORM_DATA);
068        }
069
070
071        /**
072         * Create a new MockMultipartFile with the given content.
073         * @param name the name of the file
074         * @param content the content of the file
075         */
076        public MockMultipartHttpServletRequestBuilder file(String name, byte[] content) {
077                this.files.add(new MockMultipartFile(name, content));
078                return this;
079        }
080
081        /**
082         * Add the given MockMultipartFile.
083         * @param file the multipart file
084         */
085        public MockMultipartHttpServletRequestBuilder file(MockMultipartFile file) {
086                this.files.add(file);
087                return this;
088        }
089
090        @Override
091        public Object merge(Object parent) {
092                if (parent == null) {
093                        return this;
094                }
095                if (parent instanceof MockHttpServletRequestBuilder) {
096                        super.merge(parent);
097                        if (parent instanceof MockMultipartHttpServletRequestBuilder) {
098                                MockMultipartHttpServletRequestBuilder parentBuilder = (MockMultipartHttpServletRequestBuilder) parent;
099                                this.files.addAll(parentBuilder.files);
100                        }
101                }
102                else {
103                        throw new IllegalArgumentException("Cannot merge with [" + parent.getClass().getName() + "]");
104                }
105                return this;
106        }
107
108        /**
109         * Create a new {@link MockMultipartHttpServletRequest} based on the
110         * supplied {@code ServletContext} and the {@code MockMultipartFiles}
111         * added to this builder.
112         */
113        @Override
114        protected final MockHttpServletRequest createServletRequest(ServletContext servletContext) {
115                MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest(servletContext);
116                for (MockMultipartFile file : this.files) {
117                        request.addFile(file);
118                }
119                return request;
120        }
121
122}