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    }