001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 package org.apache.myfaces.tobago.webapp; 021 022 import org.apache.commons.fileupload.FileItem; 023 import org.apache.commons.fileupload.FileUploadException; 024 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 025 import org.apache.commons.fileupload.servlet.ServletFileUpload; 026 import org.apache.commons.logging.Log; 027 import org.apache.commons.logging.LogFactory; 028 029 import javax.faces.FacesException; 030 import javax.servlet.http.HttpServletRequest; 031 import javax.servlet.http.HttpServletRequestWrapper; 032 import java.io.File; 033 import java.io.UnsupportedEncodingException; 034 import java.util.Arrays; 035 import java.util.Collections; 036 import java.util.Enumeration; 037 import java.util.HashMap; 038 import java.util.List; 039 import java.util.Locale; 040 import java.util.Map; 041 042 import static org.apache.myfaces.tobago.TobagoConstants.FORM_ACCEPT_CHARSET; 043 044 public class TobagoMultipartFormdataRequest extends HttpServletRequestWrapper { 045 046 private static final Log LOG = LogFactory.getLog(TobagoMultipartFormdataRequest.class); 047 048 public static final long ONE_KB = 1024; 049 public static final long ONE_MB = ONE_KB * ONE_KB; 050 public static final long ONE_GB = ONE_KB * ONE_MB; 051 052 private Map<String, String[]> parameters; 053 054 private Map<String, FileItem> fileItems; 055 056 public TobagoMultipartFormdataRequest(HttpServletRequest request) { 057 this(request, System.getProperty("java.io.tmpdir"), ONE_MB); 058 } 059 060 public TobagoMultipartFormdataRequest(HttpServletRequest request, String repositoryPath, long maxSize) { 061 super(request); 062 init(request, repositoryPath, maxSize); 063 } 064 065 private void init(HttpServletRequest request, String repositoryPath, long maxSize) { 066 if (!ServletFileUpload.isMultipartContent(request)) { 067 String errorText = "contentType is not multipart/form-data but '" + request.getContentType() + "'"; 068 LOG.error(errorText); 069 throw new FacesException(errorText); 070 } else { 071 parameters = new HashMap<String, String[]>(); 072 fileItems = new HashMap<String, FileItem>(); 073 DiskFileItemFactory factory = new DiskFileItemFactory(); 074 075 factory.setRepository(new File(repositoryPath)); 076 077 ServletFileUpload upload = new ServletFileUpload(factory); 078 079 upload.setSizeMax(maxSize); 080 081 if (upload.getHeaderEncoding() != null) { 082 // TODO: enable configuration of 'accept-charset' 083 upload.setHeaderEncoding(FORM_ACCEPT_CHARSET); 084 } 085 List<FileItem> itemList; 086 try { 087 itemList = (List<FileItem>) upload.parseRequest(request); 088 } catch (FileUploadException e) { 089 //LOG.error(e); 090 throw new FacesException(e); 091 } 092 if (LOG.isDebugEnabled()) { 093 LOG.debug("parametercount = " + itemList.size() + " + " + request.getParameterMap().size()); 094 } 095 for (FileItem item : itemList) { 096 String key = item.getFieldName(); 097 if (LOG.isDebugEnabled()) { 098 String value = item.getString(); 099 if (value.length() > 100) { 100 value = value.substring(0, 100) + " [...]"; 101 } 102 LOG.debug("Parameter: '" + key + "'='" + value + "' isFormField=" + item.isFormField() 103 + " contentType='" + item.getContentType() + "'"); 104 } 105 if (item.isFormField()) { 106 String newValue; 107 try { 108 // TODO: enable configuration of 'accept-charset' 109 newValue = item.getString(FORM_ACCEPT_CHARSET); 110 } catch (UnsupportedEncodingException e) { 111 LOG.error("Caught: " + e.getMessage(), e); 112 newValue = item.getString(); 113 } 114 115 addParameter(key, newValue); 116 } else { 117 fileItems.put(key, item); 118 } 119 } 120 121 // merging the GET parameters: 122 Enumeration e = request.getParameterNames(); 123 while(e.hasMoreElements()) { 124 final String name = (String) e.nextElement(); 125 final String[] newValues = request.getParameterValues(name); 126 if (LOG.isDebugEnabled()) { 127 LOG.debug("Parameter: '" + name + "'='" + Arrays.toString(newValues) + "' (GET)"); 128 } 129 for (String newValue : newValues) { 130 addParameter(name, newValue); 131 } 132 } 133 } 134 } 135 136 private void addParameter(String key, String newValue) { 137 final String[] inStock = parameters.get(key); 138 final String[] values; 139 if (inStock == null) { 140 values = new String[]{newValue}; 141 } else { 142 values = new String[inStock.length + 1]; 143 System.arraycopy(inStock, 0, values, 0, inStock.length); 144 values[inStock.length] = newValue; 145 } 146 parameters.put(key, values); 147 } 148 149 public FileItem getFileItem(String key) { 150 if (fileItems != null) { 151 return fileItems.get(key); 152 } 153 return null; 154 } 155 156 public String getParameter(String key) { 157 String parameter = null; 158 String[] values = (String[]) parameters.get(key); 159 if (values != null) { 160 parameter = values[0]; 161 } 162 return parameter; 163 } 164 165 public Enumeration getParameterNames() { 166 return Collections.enumeration(parameters.keySet()); 167 } 168 169 public String[] getParameterValues(String key) { 170 return (String[]) parameters.get(key); 171 } 172 173 public Map getParameterMap() { 174 return parameters; 175 } 176 177 public static long getMaxSize(String param) { 178 if (param != null) { 179 String number = param.toLowerCase(Locale.ENGLISH); 180 long factor = 1; 181 if (number.endsWith("g")) { 182 factor = ONE_GB; 183 number = number.substring(0, number.length() - 1); 184 } else if (number.endsWith("m")) { 185 factor = ONE_MB; 186 number = number.substring(0, number.length() - 1); 187 } else if (number.endsWith("k")) { 188 factor = ONE_KB; 189 number = number.substring(0, number.length() - 1); 190 } 191 try { 192 return Long.parseLong(number.trim()) * factor; 193 } catch (NumberFormatException e) { 194 LOG.error("Given max file size for " 195 + TobagoMultipartFormdataRequest.class.getName() + " " + param + " couldn't parsed to a number"); 196 } 197 } 198 return ONE_MB; 199 } 200 }