001 /*
002 * This file is part of the Echo Point Project. This project is a
003 * collection of Components that have extended the Echo Web Application
004 * Framework Version 3.
005 *
006 * Version: MPL 1.1
007 *
008 * The contents of this file are subject to the Mozilla Public License Version
009 * 1.1 (the "License"); you may not use this file except in compliance with
010 * the License. You may obtain a copy of the License at
011 * http://www.mozilla.org/MPL/
012 *
013 * Software distributed under the License is distributed on an "AS IS" basis,
014 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
015 * for the specific language governing rights and limitations under the
016 * License.
017 */
018 package echopoint.tucana;
019
020 import echopoint.tucana.event.UploadStartEvent;
021 import nextapp.echo.app.ApplicationInstance;
022 import nextapp.echo.webcontainer.Connection;
023 import org.apache.commons.fileupload.FileItem;
024 import org.apache.commons.fileupload.FileItemIterator;
025 import org.apache.commons.fileupload.FileItemStream;
026 import org.apache.commons.fileupload.FileUploadBase;
027 import org.apache.commons.fileupload.MultipartStream;
028 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
029 import org.apache.commons.fileupload.servlet.ServletFileUpload;
030 import org.apache.commons.io.FilenameUtils;
031 import org.apache.commons.io.IOUtils;
032
033 import java.util.Set;
034
035 /**
036 * {@link UploadSPI} implementation that uses the
037 * <a href='http://jakarta.apache.org/commons/fileupload' target='_blank'>Jakarta
038 * Commons FileUpload</a> library.
039 *
040 * @author Echo File Transfer Library
041 * @version $Id: JakartaCommonsFileUploadProvider.java 204 2009-05-20 18:50:57Z sptrakesh $
042 */
043 public class JakartaCommonsFileUploadProvider extends AbstractFileUploadProvider
044 {
045 /**
046 * @see UploadSPI#handleUpload(nextapp.echo.webcontainer.Connection ,
047 * FileUploadSelector, String, UploadProgress)
048 */
049 public void handleUpload( final Connection conn,
050 final FileUploadSelector uploadSelect, final String uploadIndex,
051 final UploadProgress progress ) throws Exception
052 {
053 final ApplicationInstance app = conn.getUserInstance().getApplicationInstance();
054
055 DiskFileItemFactory itemFactory = new DiskFileItemFactory();
056 itemFactory.setRepository( getDiskCacheLocation() );
057 itemFactory.setSizeThreshold( getMemoryCacheThreshold() );
058
059 String encoding = conn.getRequest().getCharacterEncoding();
060 if ( encoding == null )
061 {
062 encoding = "UTF-8";
063 }
064
065 ServletFileUpload upload = new ServletFileUpload( itemFactory );
066 upload.setHeaderEncoding( encoding );
067 upload.setProgressListener( new UploadProgressListener( progress ) );
068
069 long sizeLimit = uploadSelect.getUploadSizeLimit();
070 if ( sizeLimit == 0 ) sizeLimit = getFileUploadSizeLimit();
071 if ( sizeLimit != NO_SIZE_LIMIT ) { upload.setSizeMax( sizeLimit ); }
072
073 String fileName = null;
074 String contentType = null;
075
076 try
077 {
078 FileItemIterator iter = upload.getItemIterator( conn.getRequest() );
079 if ( iter.hasNext() )
080 {
081 FileItemStream stream = iter.next();
082
083 if ( !stream.isFormField() )
084 {
085 fileName = FilenameUtils.getName( stream.getName() );
086 contentType = stream.getContentType();
087
088 final Set<String> types = uploadSelect.getContentTypeFilter();
089 if ( !types.isEmpty() )
090 {
091 if ( ! types.contains( contentType ) )
092 {
093 app.enqueueTask( uploadSelect.getTaskQueue(),
094 new InvalidContentTypeRunnable( uploadSelect, uploadIndex,
095 fileName, contentType, progress ) );
096 return;
097 }
098 }
099
100 progress.setStatus( Status.inprogress );
101 uploadSelect.notifyCallback( new UploadStartEvent( uploadSelect,
102 uploadIndex, fileName, contentType ) );
103 final FileItem item = itemFactory.createItem( fileName,
104 contentType, false, stream.getName() );
105 IOUtils.copy( stream.openStream(), item.getOutputStream() );
106
107 app.enqueueTask( uploadSelect.getTaskQueue(), new FinishRunnable(
108 uploadSelect, uploadIndex, fileName, item, progress ) );
109
110 return;
111 }
112 }
113
114 app.enqueueTask( uploadSelect.getTaskQueue(), new FailRunnable(
115 uploadSelect, uploadIndex, fileName, contentType,
116 new RuntimeException( "No multi-part content!" ), progress ) );
117 }
118 catch ( final FileUploadBase.SizeLimitExceededException e )
119 {
120 app.enqueueTask( uploadSelect.getTaskQueue(), new FailRunnable(
121 uploadSelect, uploadIndex, fileName, contentType,
122 new UploadSizeLimitExceededException( e ), progress ) );
123 }
124 catch ( final FileUploadBase.FileSizeLimitExceededException e )
125 {
126 app.enqueueTask( uploadSelect.getTaskQueue(), new FailRunnable(
127 uploadSelect, uploadIndex, fileName, contentType,
128 new UploadSizeLimitExceededException( e ), progress ) );
129 }
130 catch ( final MultipartStream.MalformedStreamException e )
131 {
132 app.enqueueTask( uploadSelect.getTaskQueue(), new CancelRunnable(
133 uploadSelect, uploadIndex, fileName, contentType, e, progress ) );
134 }
135 }
136 }