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.web.portlet.multipart;
018
019import java.util.Collections;
020import java.util.Enumeration;
021import java.util.HashMap;
022import java.util.HashSet;
023import java.util.Iterator;
024import java.util.List;
025import java.util.Map;
026import java.util.Set;
027import javax.portlet.ActionRequest;
028import javax.portlet.filter.ActionRequestWrapper;
029
030import org.springframework.util.LinkedMultiValueMap;
031import org.springframework.util.MultiValueMap;
032import org.springframework.web.multipart.MultipartFile;
033
034/**
035 * Default implementation of the {@link MultipartActionRequest} interface.
036 * Provides management of pre-generated parameter values.
037 *
038 * @author Juergen Hoeller
039 * @author Arjen Poutsma
040 * @since 2.0
041 * @see PortletMultipartResolver
042 */
043public class DefaultMultipartActionRequest extends ActionRequestWrapper implements MultipartActionRequest {
044
045        private MultiValueMap<String, MultipartFile> multipartFiles;
046
047        private Map<String, String[]> multipartParameters;
048
049        private Map<String, String> multipartParameterContentTypes;
050
051
052        /**
053         * Wrap the given Portlet ActionRequest in a MultipartActionRequest.
054         * @param request the request to wrap
055         * @param mpFiles a map of the multipart files
056         * @param mpParams a map of the parameters to expose,
057         * with Strings as keys and String arrays as values
058         */
059        public DefaultMultipartActionRequest(ActionRequest request, MultiValueMap<String, MultipartFile> mpFiles,
060                        Map<String, String[]> mpParams, Map<String, String> mpParamContentTypes) {
061
062                super(request);
063                setMultipartFiles(mpFiles);
064                setMultipartParameters(mpParams);
065                setMultipartParameterContentTypes(mpParamContentTypes);
066        }
067
068        /**
069         * Wrap the given Portlet ActionRequest in a MultipartActionRequest.
070         * @param request the request to wrap
071         */
072        protected DefaultMultipartActionRequest(ActionRequest request) {
073                super(request);
074        }
075
076
077        @Override
078        public Iterator<String> getFileNames() {
079                return getMultipartFiles().keySet().iterator();
080        }
081
082        @Override
083        public MultipartFile getFile(String name) {
084                return getMultipartFiles().getFirst(name);
085        }
086
087        @Override
088        public List<MultipartFile> getFiles(String name) {
089                List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
090                if (multipartFiles != null) {
091                        return multipartFiles;
092                }
093                else {
094                        return Collections.emptyList();
095                }
096        }
097
098
099        @Override
100        public Map<String, MultipartFile> getFileMap() {
101                return getMultipartFiles().toSingleValueMap();
102        }
103
104        @Override
105        public MultiValueMap<String, MultipartFile> getMultiFileMap() {
106                return getMultipartFiles();
107        }
108
109        @Override
110        public Enumeration<String> getParameterNames() {
111                Set<String> paramNames = new HashSet<String>();
112                Enumeration<String> paramEnum = super.getParameterNames();
113                while (paramEnum.hasMoreElements()) {
114                        paramNames.add(paramEnum.nextElement());
115                }
116                paramNames.addAll(getMultipartParameters().keySet());
117                return Collections.enumeration(paramNames);
118        }
119
120        @Override
121        public String getParameter(String name) {
122                String[] values = getMultipartParameters().get(name);
123                if (values != null) {
124                        return (values.length > 0 ? values[0] : null);
125                }
126                return super.getParameter(name);
127        }
128
129        @Override
130        public String[] getParameterValues(String name) {
131                String[] values = getMultipartParameters().get(name);
132                if (values != null) {
133                        return values;
134                }
135                return super.getParameterValues(name);
136        }
137
138        @Override
139        public Map<String, String[]> getParameterMap() {
140                Map<String, String[]> paramMap = new HashMap<String, String[]>();
141                paramMap.putAll(super.getParameterMap());
142                paramMap.putAll(getMultipartParameters());
143                return paramMap;
144        }
145
146        @Override
147        public String getMultipartContentType(String paramOrFileName) {
148                MultipartFile file = getFile(paramOrFileName);
149                if (file != null) {
150                        return file.getContentType();
151                }
152                else {
153                        return getMultipartParameterContentTypes().get(paramOrFileName);
154                }
155        }
156
157
158        /**
159         * Set a Map with parameter names as keys and list of MultipartFile objects as values.
160         * To be invoked by subclasses on initialization.
161         */
162        protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
163                this.multipartFiles =
164                                new LinkedMultiValueMap<String, MultipartFile>(Collections.unmodifiableMap(multipartFiles));
165        }
166
167        /**
168         * Obtain the MultipartFile Map for retrieval,
169         * lazily initializing it if necessary.
170         * @see #initializeMultipart()
171         */
172        protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
173                if (this.multipartFiles == null) {
174                        initializeMultipart();
175                }
176                return this.multipartFiles;
177        }
178
179        /**
180         * Set a Map with parameter names as keys and String array objects as values.
181         * To be invoked by subclasses on initialization.
182         */
183        protected final void setMultipartParameters(Map<String, String[]> multipartParameters) {
184                this.multipartParameters = multipartParameters;
185        }
186
187        /**
188         * Obtain the multipart parameter Map for retrieval,
189         * lazily initializing it if necessary.
190         * @see #initializeMultipart()
191         */
192        protected Map<String, String[]> getMultipartParameters() {
193                if (this.multipartParameters == null) {
194                        initializeMultipart();
195                }
196                return this.multipartParameters;
197        }
198
199        /**
200         * Set a Map with parameter names as keys and content type Strings as values.
201         * To be invoked by subclasses on initialization.
202         */
203        protected final void setMultipartParameterContentTypes(Map<String, String> multipartParameterContentTypes) {
204                this.multipartParameterContentTypes = multipartParameterContentTypes;
205        }
206
207        /**
208         * Obtain the multipart parameter content type Map for retrieval,
209         * lazily initializing it if necessary.
210         * @see #initializeMultipart()
211         */
212        protected Map<String, String> getMultipartParameterContentTypes() {
213                if (this.multipartParameterContentTypes == null) {
214                        initializeMultipart();
215                }
216                return this.multipartParameterContentTypes;
217        }
218
219
220        /**
221         * Lazily initialize the multipart request, if possible.
222         * Only called if not already eagerly initialized.
223         */
224        protected void initializeMultipart() {
225                throw new IllegalStateException("Multipart request not initialized");
226        }
227
228}