001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.upload;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.io.ByteArrayFileInputStream;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.upload.FileItem;
022    import com.liferay.portal.kernel.upload.UploadException;
023    import com.liferay.portal.kernel.upload.UploadServletRequest;
024    import com.liferay.portal.kernel.util.ArrayUtil;
025    import com.liferay.portal.kernel.util.FileUtil;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.SystemProperties;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.util.PrefsPropsUtil;
031    import com.liferay.portal.util.WebKeys;
032    
033    import java.io.File;
034    import java.io.IOException;
035    import java.io.InputStream;
036    
037    import java.util.ArrayList;
038    import java.util.Collections;
039    import java.util.Enumeration;
040    import java.util.HashMap;
041    import java.util.LinkedHashMap;
042    import java.util.LinkedHashSet;
043    import java.util.List;
044    import java.util.Map;
045    import java.util.Set;
046    
047    import javax.servlet.ServletInputStream;
048    import javax.servlet.http.HttpServletRequest;
049    import javax.servlet.http.HttpServletRequestWrapper;
050    
051    import org.apache.commons.fileupload.FileUploadBase;
052    import org.apache.commons.fileupload.servlet.ServletFileUpload;
053    
054    /**
055     * @author Brian Wing Shun Chan
056     * @author Zongliang Li
057     * @author Harry Mark
058     * @author Raymond Aug??
059     */
060    public class UploadServletRequestImpl
061            extends HttpServletRequestWrapper implements UploadServletRequest {
062    
063            public static File getTempDir() throws SystemException {
064                    if (_tempDir == null) {
065                            _tempDir = new File(
066                                    PrefsPropsUtil.getString(
067                                            PropsKeys.UPLOAD_SERVLET_REQUEST_IMPL_TEMP_DIR,
068                                            SystemProperties.get(SystemProperties.TMP_DIR)));
069                    }
070    
071                    return _tempDir;
072            }
073    
074            public static void setTempDir(File tempDir) {
075                    _tempDir = tempDir;
076            }
077    
078            public UploadServletRequestImpl(HttpServletRequest request) {
079                    super(request);
080    
081                    _fileParameters = new LinkedHashMap<String, FileItem[]>();
082                    _regularParameters = new LinkedHashMap<String, List<String>>();
083    
084                    try {
085                            ServletFileUpload servletFileUpload = new LiferayFileUpload(
086                                    new LiferayFileItemFactory(getTempDir()), request);
087    
088                            servletFileUpload.setSizeMax(
089                                    PrefsPropsUtil.getLong(
090                                            PropsKeys.UPLOAD_SERVLET_REQUEST_IMPL_MAX_SIZE));
091    
092                            _liferayServletRequest = new LiferayServletRequest(request);
093    
094                            List<LiferayFileItem> liferayFileItemsList =
095                                    servletFileUpload.parseRequest(_liferayServletRequest);
096    
097                            _liferayServletRequest.setFinishedReadingOriginalStream(true);
098    
099                            for (LiferayFileItem liferayFileItem : liferayFileItemsList) {
100                                    if (liferayFileItem.isFormField()) {
101                                            liferayFileItem.setString(request.getCharacterEncoding());
102    
103                                            String fieldName = liferayFileItem.getFieldName();
104    
105                                            if (!_regularParameters.containsKey(fieldName)) {
106                                                    _regularParameters.put(
107                                                            fieldName, new ArrayList<String>());
108                                            }
109    
110                                            List<String> values = _regularParameters.get(fieldName);
111    
112                                            if (liferayFileItem.getSize() >
113                                                            LiferayFileItem.THRESHOLD_SIZE) {
114    
115                                                    StringBundler sb = new StringBundler(5);
116    
117                                                    sb.append("The field ");
118                                                    sb.append(fieldName);
119                                                    sb.append(" exceeds its maximum permitted size of ");
120                                                    sb.append(LiferayFileItem.THRESHOLD_SIZE);
121                                                    sb.append(" bytes");
122    
123                                                    UploadException uploadException = new UploadException(
124                                                            sb.toString());
125    
126                                                    uploadException.setExceededLiferayFileItemSizeLimit(
127                                                            true);
128                                                    uploadException.setExceededSizeLimit(true);
129    
130                                                    request.setAttribute(
131                                                            WebKeys.UPLOAD_EXCEPTION, uploadException);
132                                            }
133    
134                                            values.add(liferayFileItem.getEncodedString());
135    
136                                            continue;
137                                    }
138    
139                                    FileItem[] liferayFileItems = _fileParameters.get(
140                                            liferayFileItem.getFieldName());
141    
142                                    if (liferayFileItems == null) {
143                                            liferayFileItems = new LiferayFileItem[] {liferayFileItem};
144                                    }
145                                    else {
146                                            LiferayFileItem[] newLiferayFileItems =
147                                                    new LiferayFileItem[liferayFileItems.length + 1];
148    
149                                            System.arraycopy(
150                                                    liferayFileItems, 0, newLiferayFileItems, 0,
151                                                    liferayFileItems.length);
152    
153                                            newLiferayFileItems[newLiferayFileItems.length - 1] =
154                                                    liferayFileItem;
155    
156                                            liferayFileItems = newLiferayFileItems;
157                                    }
158    
159                                    _fileParameters.put(
160                                            liferayFileItem.getFieldName(), liferayFileItems);
161                            }
162                    }
163                    catch (Exception e) {
164                            UploadException uploadException = new UploadException(e);
165    
166                            if (e instanceof FileUploadBase.FileSizeLimitExceededException ||
167                                    e instanceof FileUploadBase.SizeLimitExceededException ) {
168    
169                                    uploadException.setExceededSizeLimit(true);
170                            }
171    
172                            request.setAttribute(WebKeys.UPLOAD_EXCEPTION, uploadException);
173    
174                            if (_log.isDebugEnabled()) {
175                                    _log.debug(e, e);
176                            }
177                    }
178            }
179    
180            public UploadServletRequestImpl(
181                    HttpServletRequest request, Map<String, FileItem[]> fileParams,
182                    Map<String, List<String>> regularParams) {
183    
184                    super(request);
185    
186                    _fileParameters = new LinkedHashMap<String, FileItem[]>();
187                    _regularParameters = new LinkedHashMap<String, List<String>>();
188    
189                    if (fileParams != null) {
190                            _fileParameters.putAll(fileParams);
191                    }
192    
193                    if (regularParams != null) {
194                            _regularParameters.putAll(regularParams);
195                    }
196            }
197    
198            @Override
199            public void cleanUp() {
200                    if ((_fileParameters != null) && !_fileParameters.isEmpty()) {
201                            for (FileItem[] liferayFileItems : _fileParameters.values()) {
202                                    for (FileItem liferayFileItem : liferayFileItems) {
203                                            liferayFileItem.delete();
204                                    }
205                            }
206                    }
207    
208                    _liferayServletRequest.cleanUp();
209            }
210    
211            @Override
212            public String getContentType(String name) {
213                    FileItem[] liferayFileItems = _fileParameters.get(name);
214    
215                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
216                            FileItem liferayFileItem = liferayFileItems[0];
217    
218                            return liferayFileItem.getContentType();
219                    }
220    
221                    return null;
222            }
223    
224            @Override
225            public File getFile(String name) {
226                    return getFile(name, false);
227            }
228    
229            @Override
230            public File getFile(String name, boolean forceCreate) {
231                    if (getFileName(name) == null) {
232                            return null;
233                    }
234    
235                    FileItem[] liferayFileItems = _fileParameters.get(name);
236    
237                    if (ArrayUtil.isEmpty(liferayFileItems)) {
238                            return null;
239                    }
240    
241                    FileItem liferayFileItem = liferayFileItems[0];
242    
243                    long size = liferayFileItem.getSize();
244    
245                    if ((size > 0) && (size <= liferayFileItem.getSizeThreshold())) {
246                            forceCreate = true;
247                    }
248    
249                    File file = liferayFileItem.getStoreLocation();
250    
251                    if (liferayFileItem.isInMemory() && forceCreate) {
252                            try {
253                                    FileUtil.write(file, liferayFileItem.getInputStream());
254                            }
255                            catch (IOException ioe) {
256                                    if (_log.isWarnEnabled()) {
257                                            _log.warn(
258                                                    "Unable to write temporary file " +
259                                                            file.getAbsolutePath(),
260                                                    ioe);
261                                    }
262                            }
263                    }
264    
265                    return file;
266            }
267    
268            @Override
269            public InputStream getFileAsStream(String name) throws IOException {
270                    return getFileAsStream(name, true);
271            }
272    
273            @Override
274            public InputStream getFileAsStream(String name, boolean deleteOnClose)
275                    throws IOException {
276    
277                    if (getFileName(name) == null) {
278                            return null;
279                    }
280    
281                    InputStream inputStream = null;
282    
283                    FileItem[] liferayFileItems = _fileParameters.get(name);
284    
285                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
286                            FileItem liferayFileItem = liferayFileItems[0];
287    
288                            inputStream = getInputStream(liferayFileItem, deleteOnClose);
289                    }
290    
291                    return inputStream;
292            }
293    
294            @Override
295            public String getFileName(String name) {
296                    FileItem[] liferayFileItems = _fileParameters.get(name);
297    
298                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
299                            FileItem liferayFileItem = liferayFileItems[0];
300    
301                            return liferayFileItem.getFileName();
302                    }
303    
304                    return null;
305            }
306    
307            @Override
308            public String[] getFileNames(String name) {
309                    FileItem[] liferayFileItems = _fileParameters.get(name);
310    
311                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
312                            String[] fileNames = new String[liferayFileItems.length];
313    
314                            for (int i = 0; i < liferayFileItems.length; i++) {
315                                    FileItem liferayFileItem = liferayFileItems[i];
316    
317                                    fileNames[i] = liferayFileItem.getFileName();
318                            }
319    
320                            return fileNames;
321                    }
322    
323                    return null;
324            }
325    
326            @Override
327            public File[] getFiles(String name) {
328                    String[] fileNames = getFileNames(name);
329    
330                    if (fileNames == null) {
331                            return null;
332                    }
333    
334                    FileItem[] liferayFileItems = _fileParameters.get(name);
335    
336                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
337                            File[] files = new File[liferayFileItems.length];
338    
339                            for (int i = 0; i < liferayFileItems.length; i++) {
340                                    FileItem liferayFileItem = liferayFileItems[i];
341    
342                                    if (Validator.isNotNull(liferayFileItem.getFileName())) {
343                                            files[i] = liferayFileItem.getStoreLocation();
344                                    }
345                            }
346    
347                            return files;
348                    }
349    
350                    return null;
351            }
352    
353            @Override
354            public InputStream[] getFilesAsStream(String name) throws IOException {
355                    return getFilesAsStream(name, true);
356            }
357    
358            @Override
359            public InputStream[] getFilesAsStream(String name, boolean deleteOnClose)
360                    throws IOException {
361    
362                    String[] fileNames = getFileNames(name);
363    
364                    if (fileNames == null) {
365                            return null;
366                    }
367    
368                    InputStream[] inputStreams = null;
369    
370                    FileItem[] liferayFileItems = _fileParameters.get(name);
371    
372                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
373                            inputStreams = new InputStream[liferayFileItems.length];
374    
375                            for (int i = 0; i < liferayFileItems.length; i++) {
376                                    FileItem liferayFileItem = liferayFileItems[i];
377    
378                                    if (Validator.isNotNull(liferayFileItem.getFileName())) {
379                                            inputStreams[i] = getInputStream(
380                                                    liferayFileItem, deleteOnClose);
381                                    }
382                            }
383                    }
384    
385                    return inputStreams;
386            }
387    
388            @Override
389            public String getFullFileName(String name) {
390                    FileItem[] liferayFileItems = _fileParameters.get(name);
391    
392                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
393                            FileItem liferayFileItem = liferayFileItems[0];
394    
395                            return liferayFileItem.getFullFileName();
396                    }
397    
398                    return null;
399            }
400    
401            @Override
402            public ServletInputStream getInputStream() throws IOException {
403                    if (_liferayServletRequest != null) {
404                            return _liferayServletRequest.getInputStream();
405                    }
406    
407                    return super.getInputStream();
408            }
409    
410            @Override
411            public Map<String, FileItem[]> getMultipartParameterMap() {
412                    return _fileParameters;
413            }
414    
415            @Override
416            public String getParameter(String name) {
417                    List<String> values = _regularParameters.get(name);
418    
419                    if ((values != null) && !values.isEmpty()) {
420                            return values.get(0);
421                    }
422    
423                    return super.getParameter(name);
424            }
425    
426            @Override
427            public Map<String, String[]> getParameterMap() {
428                    Map<String, String[]> map = new HashMap<String, String[]>();
429    
430                    Enumeration<String> enu = getParameterNames();
431    
432                    while (enu.hasMoreElements()) {
433                            String name = enu.nextElement();
434    
435                            map.put(name, getParameterValues(name));
436                    }
437    
438                    return map;
439            }
440    
441            @Override
442            public Enumeration<String> getParameterNames() {
443                    Set<String> parameterNames = new LinkedHashSet<String>();
444    
445                    Enumeration<String> enu = super.getParameterNames();
446    
447                    while (enu.hasMoreElements()) {
448                            parameterNames.add(enu.nextElement());
449                    }
450    
451                    parameterNames.addAll(_regularParameters.keySet());
452    
453                    return Collections.enumeration(parameterNames);
454            }
455    
456            @Override
457            public String[] getParameterValues(String name) {
458                    String[] parameterValues = null;
459    
460                    List<String> values = _regularParameters.get(name);
461    
462                    if (values != null) {
463                            parameterValues = values.toArray(new String[values.size()]);
464                    }
465    
466                    String[] parentParameterValues = super.getParameterValues(name);
467    
468                    if (parameterValues == null) {
469                            return parentParameterValues;
470                    }
471                    else if (parentParameterValues == null) {
472                            return parameterValues;
473                    }
474    
475                    return ArrayUtil.append(parameterValues, parentParameterValues);
476            }
477    
478            @Override
479            public Map<String, List<String>> getRegularParameterMap() {
480                    return _regularParameters;
481            }
482    
483            @Override
484            public Long getSize(String name) {
485                    FileItem[] liferayFileItems = _fileParameters.get(name);
486    
487                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
488                            FileItem liferayFileItem = liferayFileItems[0];
489    
490                            return new Long(liferayFileItem.getSize());
491                    }
492    
493                    return null;
494            }
495    
496            @Override
497            public Boolean isFormField(String name) {
498                    FileItem[] liferayFileItems = _fileParameters.get(name);
499    
500                    if (ArrayUtil.isNotEmpty(liferayFileItems)) {
501                            FileItem liferayFileItem = liferayFileItems[0];
502    
503                            return new Boolean(liferayFileItem.isFormField());
504                    }
505    
506                    return null;
507            }
508    
509            protected InputStream getInputStream(
510                            FileItem liferayFileItem, boolean deleteOnClose)
511                    throws IOException {
512    
513                    InputStream inputStream = null;
514    
515                    if (liferayFileItem.isInMemory() && (liferayFileItem.getSize() > 0)) {
516                            inputStream = liferayFileItem.getInputStream();
517                    }
518                    else if (!liferayFileItem.isInMemory()) {
519                            inputStream = new ByteArrayFileInputStream(
520                                    liferayFileItem.getStoreLocation(),
521                                    liferayFileItem.getSizeThreshold(), deleteOnClose);
522                    }
523    
524                    return inputStream;
525            }
526    
527            private static Log _log = LogFactoryUtil.getLog(
528                    UploadServletRequestImpl.class);
529    
530            private static File _tempDir;
531    
532            private Map<String, FileItem[]> _fileParameters;
533            private LiferayServletRequest _liferayServletRequest;
534            private Map<String, List<String>> _regularParameters;
535    
536    }