/** * Copyright 2005-2010 hdiv.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hdiv.web.multipart; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hdiv.config.multipart.IMultipartConfig; import org.hdiv.filter.RequestWrapper; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest; /** * Servlet-based MultipartResolver implementation for * <a href="http://jakarta.apache.org/commons/fileupload">Jakarta Commons FileUpload</a> * 1.2 or higher and HDIV 2.06 or higher. * * <p>Provides maxUploadSize, maxInMemorySize, and defaultEncoding settings as * bean properties (inherited from CommonsFileUploadSupport). See respective * ServletFileUpload / DiskFileItemFactory properties (sizeMax, sizeThreshold, * headerEncoding) for details in terms of defaults and accepted values. * * <p>Saves temporary files to the servlet container's temporary directory. * Needs to be initialized <i>either</i> by an application context <i>or</i> * via the constructor that takes a ServletContext (for standalone usage). * * <p><b>NOTE:</b> As of Spring 2.0, this multipart resolver requires * Commons FileUpload 1.1 or higher. The implementation does not use * any deprecated FileUpload 1.0 API anymore, to be compatible with future * Commons FileUpload releases. * * @author Gorka Vicente * @since HDIV 2.0.6 * @see #CommonsMultipartResolver(ServletContext) * @see CommonsMultipartFile * @see org.springframework.web.portlet.multipart.PortletMultipartResolver * @see org.apache.commons.fileupload.servlet.ServletFileUpload * @see org.apache.commons.fileupload.disk.DiskFileItemFactory */ public class HDIVMultipartResolver extends CommonsMultipartResolver { private static Log log = LogFactory.getLog(HDIVMultipartResolver.class); private boolean resolveLazily = false; @Override public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException { Assert.notNull(request, "Request must not be null"); if (request instanceof RequestWrapper) { final RequestWrapper requestWrapper = (RequestWrapper) request; Exception multipartException = (Exception) request.getAttribute(IMultipartConfig.FILEUPLOAD_EXCEPTION); if (multipartException != null) { if (multipartException instanceof MaxUploadSizeExceededException) { throw (MaxUploadSizeExceededException) multipartException; } else { throw new MultipartException("Could not parse multipart servlet request", multipartException); } } if (this.resolveLazily) { return new DefaultMultipartHttpServletRequest(requestWrapper) { @Override protected void initializeMultipart() { setMultipartFiles(getMultipartFileElements(requestWrapper.getFileElements())); setMultipartParameters(getMultipartTextElements(requestWrapper.getTextElements())); } }; } else { return new DefaultMultipartHttpServletRequest(request, getMultipartFileElements(requestWrapper.getFileElements()), getMultipartTextElements(requestWrapper.getTextElements())); } } else { //The normal behaviour return super.resolveMultipart(request); } } /** * Return the multipart files as Map of field name to MultipartFile instance. */ public MultiValueMap<String, MultipartFile> getMultipartFileElements(Hashtable fileElements) { MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>(); for(Object key: fileElements.keySet()){ multipartFiles.add((String)key, (MultipartFile)fileElements.get(key)); } return multipartFiles; } /** * Return the multipart parameters as Map of field name to form field String value. */ public Map<String, String[]> getMultipartTextElements(Hashtable textElements) { Map<String, String[]> multipartParameters = new HashMap<String, String[]>(); multipartParameters.putAll(textElements); return multipartParameters; } /** * Return the multipart files as Map of field name to MultipartFile instance. */ public Collection<MultipartFile> getMultipartFileValues(Hashtable fileElements) { Collection<MultipartFile> multipartFileValues = new ArrayList<MultipartFile>(); multipartFileValues.addAll(fileElements.values()); return multipartFileValues; } @Override public void cleanupMultipart(MultipartHttpServletRequest request) { if (request != null) { DefaultMultipartHttpServletRequest defaultRequest = (DefaultMultipartHttpServletRequest) request; RequestWrapper requestWrapper = (RequestWrapper)defaultRequest.getRequest(); //Call to the original method this.cleanupFileItems(getMultipartFileElements(requestWrapper.getFileElements())); } } /** * Set whether to resolve the multipart request lazily at the time of * file or parameter access. * <p>Default is "false", resolving the multipart elements immediately, throwing * corresponding exceptions at the time of the {@link #resolveMultipart} call. * Switch this to "true" for lazy multipart parsing, throwing parse exceptions * once the application attempts to obtain multipart files or parameters. */ public void setResolveLazily(boolean resolveLazily) { super.setResolveLazily(resolveLazily); this.resolveLazily = resolveLazily; } }