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