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