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 }