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