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}