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