/** * Copyright 2011 meltmedia * * 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.xchain.framework.servlet; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.ArrayList; import java.util.Iterator; import java.util.Enumeration; import java.io.File; import java.lang.reflect.Array; /** * * This code was adapted from code originally written by Darius Robinson. * * @author Darius Robinson * @author Christian Trimble * @author John Trimble * @author Josh Kennedy * @version 1.0 */ public class MultipartFormDataServletRequest extends HttpServletRequestWrapper { public static Logger log = LoggerFactory.getLogger(MultipartFormDataServletRequest.class); private Map<String, String[]> parameterMap = new HashMap<String, String[]>(); private Map<String, FileItem[]> fileItemMap = new HashMap<String, FileItem[]>(); public MultipartFormDataServletRequest(HttpServletRequest request, long maxSize, int sizeThreshold, String repositoryPath) throws FileUploadException { super(request); // Create the disk file item factory. DiskFileItemFactory factory = createDiskFileItemFactory(sizeThreshold, repositoryPath); ServletFileUpload servletFileUpload = new ServletFileUpload(factory); // maximum size before a FileUploadException will be thrown servletFileUpload.setSizeMax(maxSize); // parse the request. Iterator<FileItem> fileItemIterator = servletFileUpload.parseRequest(request).iterator(); // Oye! Unchecked type conversion. // create temporary maps for parameters and file items. Map<String, List<String>> parameterMap = new HashMap<String, List<String>>(); Map<String, List<FileItem>> fileItemMap = new HashMap<String, List<FileItem>>(); // populate the maps. while( fileItemIterator.hasNext() ) { FileItem fileItem = fileItemIterator.next(); if (fileItem.isFormField()) { putListMapValue(parameterMap, fileItem.getFieldName(), fileItem.getString()); } else { putListMapValue(fileItemMap, fileItem.getFieldName(), fileItem); } } // convert the array lists. convertListMapToArrayMap(parameterMap, this.parameterMap, String.class); convertListMapToArrayMap(fileItemMap, this.fileItemMap, FileItem.class); if( log.isDebugEnabled() ) { logFileItemMap(); } } public FileItem getFileItem( String name ) { FileItem fileItem = null; FileItem[] fileItemArray = (FileItem[])fileItemMap.get(name); if( fileItemArray != null ) fileItem = fileItemArray[0]; return fileItem; } public Enumeration<String> getFileItemNames() { return new IteratorEnumeration<String>(fileItemMap.keySet().iterator()); } public Map<String, FileItem[]> getFileItemMap() { return fileItemMap; } public FileItem[] getFileItemValues( String name ) { return (FileItem[])fileItemMap.get(name); } public String getParameter( String name ) { String parameter = null; String[] parameterList = (String[])parameterMap.get(name); if( parameterList != null && parameterList.length > 0 ) { parameter = parameterList[0]; } return parameter; } public Enumeration<String> getParameterNames() { return new IteratorEnumeration<String>(parameterMap.keySet().iterator()); } public Map<String, String[]> getParameterMap() { return parameterMap; } public String[] getParameterValues( String name ) { return (String[])parameterMap.get(name); } private static <K,V> Map<K, V[]> convertListMapToArrayMap(Map<K, List<V>> listMap, Map<K, V[]> arrayMap, Class<V> elementType) { if( arrayMap == null ) arrayMap = new HashMap<K, V[]>(); for( Map.Entry<K, List<V>> e : listMap.entrySet() ) { V[] valueArray = (V[]) Array.newInstance(elementType, e.getValue().size()); arrayMap.put(e.getKey(), e.getValue().toArray(valueArray)); } return arrayMap; } private static <K, V> void putListMapValue( Map<K, List<V>> map, K key, V value ) { List<V> valueArray = map.get(key); if( valueArray == null ) { valueArray = new ArrayList<V>(); map.put(key, valueArray); } valueArray.add(value); } private static DiskFileItemFactory createDiskFileItemFactory( int sizeThreshold, String repositoryPath ) throws FileUploadException { DiskFileItemFactory factory = new DiskFileItemFactory(); // the location for saving data that is larger than getSizeThreshold() File repository = new File(repositoryPath); factory.setRepository(repository); // maximum size that will be stored in memory factory.setSizeThreshold(sizeThreshold); // Check to see if repository exists; if not, try to create it; if this fails, throw an exception. if( repository.exists() ) { if( !repository.isDirectory() ) { throw new FileUploadException("Cannot upload files because the specified temporary " + "directory is of type file. (" + repository.getAbsolutePath() + ")"); } } else if( !repository.mkdir() ) { throw new FileUploadException("Cannot upload files because the specified temporary " + " does not exist, and attempts to create it have failed. (" + repository.getAbsolutePath() + ")"); } return factory; } protected void logFileItemMap() { log.debug("File item map has "+fileItemMap.keySet().size()+" keys."); Iterator<Map.Entry<String, FileItem[]>> entryIterator = fileItemMap.entrySet().iterator(); while( entryIterator.hasNext() ) { Map.Entry<String, FileItem[]> entry = entryIterator.next(); String key = entry.getKey(); FileItem[] fileItems = entry.getValue(); log.debug("Key '"+key+"' has "+fileItems.length+" entries."); for( int i = 0; i < fileItems.length; i++ ) { log.debug("Name='"+fileItems[i].getName()+"', size="+fileItems[i].getSize()+", content-type='"+fileItems[i].getContentType()+"'"); } } } } class IteratorEnumeration<T> implements Enumeration<T> { Iterator<T> wrappedIterator = null; public IteratorEnumeration( Iterator<T> wrappedIterator ) { this.wrappedIterator = wrappedIterator; } public boolean hasMoreElements() { return wrappedIterator.hasNext(); } public T nextElement() { return wrappedIterator.next(); } }