001/*
002 * Copyright 2002-2018 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.multipart.support;
018
019import java.util.Collections;
020import java.util.Enumeration;
021import java.util.LinkedHashMap;
022import java.util.LinkedHashSet;
023import java.util.Map;
024import java.util.Set;
025
026import javax.servlet.http.HttpServletRequest;
027
028import org.springframework.http.HttpHeaders;
029import org.springframework.lang.Nullable;
030import org.springframework.util.MultiValueMap;
031import org.springframework.web.multipart.MultipartFile;
032
033/**
034 * Default implementation of the
035 * {@link org.springframework.web.multipart.MultipartHttpServletRequest}
036 * interface. Provides management of pre-generated parameter values.
037 *
038 * <p>Used by {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}.
039 *
040 * @author Trevor D. Cook
041 * @author Juergen Hoeller
042 * @author Arjen Poutsma
043 * @since 29.09.2003
044 * @see org.springframework.web.multipart.MultipartResolver
045 */
046public class DefaultMultipartHttpServletRequest extends AbstractMultipartHttpServletRequest {
047
048        private static final String CONTENT_TYPE = "Content-Type";
049
050        @Nullable
051        private Map<String, String[]> multipartParameters;
052
053        @Nullable
054        private Map<String, String> multipartParameterContentTypes;
055
056
057        /**
058         * Wrap the given HttpServletRequest in a MultipartHttpServletRequest.
059         * @param request the servlet request to wrap
060         * @param mpFiles a map of the multipart files
061         * @param mpParams a map of the parameters to expose,
062         * with Strings as keys and String arrays as values
063         */
064        public DefaultMultipartHttpServletRequest(HttpServletRequest request, MultiValueMap<String, MultipartFile> mpFiles,
065                        Map<String, String[]> mpParams, Map<String, String> mpParamContentTypes) {
066
067                super(request);
068                setMultipartFiles(mpFiles);
069                setMultipartParameters(mpParams);
070                setMultipartParameterContentTypes(mpParamContentTypes);
071        }
072
073        /**
074         * Wrap the given HttpServletRequest in a MultipartHttpServletRequest.
075         * @param request the servlet request to wrap
076         */
077        public DefaultMultipartHttpServletRequest(HttpServletRequest request) {
078                super(request);
079        }
080
081
082        @Override
083        @Nullable
084        public String getParameter(String name) {
085                String[] values = getMultipartParameters().get(name);
086                if (values != null) {
087                        return (values.length > 0 ? values[0] : null);
088                }
089                return super.getParameter(name);
090        }
091
092        @Override
093        public String[] getParameterValues(String name) {
094                String[] parameterValues = super.getParameterValues(name);
095                String[] mpValues = getMultipartParameters().get(name);
096                if (mpValues == null) {
097                        return parameterValues;
098                }
099                if (parameterValues == null || getQueryString() == null) {
100                        return mpValues;
101                }
102                else {
103                        String[] result = new String[mpValues.length + parameterValues.length];
104                        System.arraycopy(mpValues, 0, result, 0, mpValues.length);
105                        System.arraycopy(parameterValues, 0, result, mpValues.length, parameterValues.length);
106                        return result;
107                }
108        }
109
110        @Override
111        public Enumeration<String> getParameterNames() {
112                Map<String, String[]> multipartParameters = getMultipartParameters();
113                if (multipartParameters.isEmpty()) {
114                        return super.getParameterNames();
115                }
116
117                Set<String> paramNames = new LinkedHashSet<>();
118                paramNames.addAll(Collections.list(super.getParameterNames()));
119                paramNames.addAll(multipartParameters.keySet());
120                return Collections.enumeration(paramNames);
121        }
122
123        @Override
124        public Map<String, String[]> getParameterMap() {
125                Map<String, String[]> result = new LinkedHashMap<>();
126                Enumeration<String> names = getParameterNames();
127                while (names.hasMoreElements()) {
128                        String name = names.nextElement();
129                        result.put(name, getParameterValues(name));
130                }
131                return result;
132        }
133
134        @Override
135        public String getMultipartContentType(String paramOrFileName) {
136                MultipartFile file = getFile(paramOrFileName);
137                if (file != null) {
138                        return file.getContentType();
139                }
140                else {
141                        return getMultipartParameterContentTypes().get(paramOrFileName);
142                }
143        }
144
145        @Override
146        public HttpHeaders getMultipartHeaders(String paramOrFileName) {
147                String contentType = getMultipartContentType(paramOrFileName);
148                if (contentType != null) {
149                        HttpHeaders headers = new HttpHeaders();
150                        headers.add(CONTENT_TYPE, contentType);
151                        return headers;
152                }
153                else {
154                        return null;
155                }
156        }
157
158
159        /**
160         * Set a Map with parameter names as keys and String array objects as values.
161         * To be invoked by subclasses on initialization.
162         */
163        protected final void setMultipartParameters(Map<String, String[]> multipartParameters) {
164                this.multipartParameters = multipartParameters;
165        }
166
167        /**
168         * Obtain the multipart parameter Map for retrieval,
169         * lazily initializing it if necessary.
170         * @see #initializeMultipart()
171         */
172        protected Map<String, String[]> getMultipartParameters() {
173                if (this.multipartParameters == null) {
174                        initializeMultipart();
175                }
176                return this.multipartParameters;
177        }
178
179        /**
180         * Set a Map with parameter names as keys and content type Strings as values.
181         * To be invoked by subclasses on initialization.
182         */
183        protected final void setMultipartParameterContentTypes(Map<String, String> multipartParameterContentTypes) {
184                this.multipartParameterContentTypes = multipartParameterContentTypes;
185        }
186
187        /**
188         * Obtain the multipart parameter content type Map for retrieval,
189         * lazily initializing it if necessary.
190         * @see #initializeMultipart()
191         */
192        protected Map<String, String> getMultipartParameterContentTypes() {
193                if (this.multipartParameterContentTypes == null) {
194                        initializeMultipart();
195                }
196                return this.multipartParameterContentTypes;
197        }
198
199}