+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Innoopract Informationssysteme GmbH - initial API and implementation
- ******************************************************************************/
-
-package org.eclipse.rwt.widgets.upload.servlet;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.List;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.*;
-
-import org.apache.commons.fileupload.*;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.eclipse.rwt.RWT;
-import org.eclipse.rwt.internal.util.URLHelper;
-import org.eclipse.rwt.service.IServiceHandler;
-import org.eclipse.rwt.widgets.IUploadConfiguration;
-import org.eclipse.rwt.widgets.internal.UploadConfiguration;
-
-
-/**
- * Handles file uploads and upload progress updates.
- * <p>
- * Implementation note: uploaded files are currently stored in the
- * java.io.tmpdir. See
- * {@link #handleFileUpload(HttpServletRequest, FileUploadStorageItem)} on
- * how to change this.
- *
- * @author stefan.roeck
- */
-public class FileUploadServiceHandler implements IServiceHandler {
-
- private static final String REQUEST_WIDGET_ID = "widgetId";
- private static final String REQUEST_PROCESS_ID = "processId";
- private static final String XML_HEAD = "<?xml version=\"1.0\" encoding=\"utf-8\"?><response>";
-
- /**
- * Holds configuration data for the upload widget.
- */
- private static final IUploadConfiguration uploadConfiguration = new UploadConfiguration();
-
- /**
- * Requests to this service handler without a valid session id are ignored for
- * security reasons. The same applies to request with widgetIds which haven't been
- * registered at the session singleton {@link FileUploadStorage}.
- */
- public void service() throws IOException, ServletException {
-
- final HttpServletRequest request = RWT.getRequest();
- final String widgetId = request.getParameter( REQUEST_WIDGET_ID );
- final String uploadProcessId = request.getParameter( REQUEST_PROCESS_ID );
- final HttpSession session = request.getSession( false );
-
- if( session != null
- && widgetId != null
- && !"".equals( widgetId )
- && uploadProcessId != null
- && !"".equals( uploadProcessId ) )
- {
- final FileUploadStorage fileUploadStorage = FileUploadStorage.getInstance();
- final FileUploadStorageItem fileUploadStorageItem = fileUploadStorage.getUploadStorageItem( widgetId );
-
- // fileUploadStorageItem can be null, if Upload widget is dispsed!
- if (ServletFileUpload.isMultipartContent(request)) {
- // Handle post-request which contains the file to upload
- handleFileUpload( request, fileUploadStorageItem, uploadProcessId );
- } else {
- // This is probably a request for updating the progress bar
- handleUpdateProgress( fileUploadStorageItem, uploadProcessId );
- }
-
- }
- }
-
- /**
- * Treats the request as a post request which contains the file to be
- * uploaded. Uses the apache commons fileupload library to
- * extract the file from the request, attaches a {@link FileUploadListener} to
- * get notified about the progress and writes the file content
- * to the given {@link FileUploadStorageItem}
- * @param request Request object, must not be null
- * @param fileUploadStorageitem Object where the file content is set to.
- * If null, nothing happens.
- * @param uploadProcessId Each upload action has a unique process identifier to
- * match subsequent polling calls to get the progress correctly to the uploaded file.
- *
- */
- private void handleFileUpload( final HttpServletRequest request,
- final FileUploadStorageItem fileUploadStorageitem,
- final String uploadProcessId )
- {
- // Ignore upload requests which have no valid widgetId
- if (fileUploadStorageitem != null && uploadProcessId != null && !"".equals( uploadProcessId )) {
-
- // Reset storage item to clear values from last upload process
- fileUploadStorageitem.reset();
-
- // Create file upload factory and upload servlet
- // You could use new DiskFileItemFactory(threshold, location)
- // to configure a custom in-memory threshold and storage location.
- // By default the upload files are stored in the java.io.tmpdir
- final FileItemFactory factory = new DiskFileItemFactory();
- final ServletFileUpload upload = new ServletFileUpload( factory );
-
- // apply configuration params
- applyConfiguration(upload);
-
- // Create a file upload progress listener
- final ProgressListener listener = new ProgressListener() {
-
- public void update( final long aBytesRead,
- final long aContentLength,
- final int anItem ) {
- fileUploadStorageitem.updateProgress( aBytesRead, aContentLength );
- }
-
- };
- // Upload servlet allows to set upload listener
- upload.setProgressListener( listener );
- fileUploadStorageitem.setUploadProcessId( uploadProcessId );
-
- FileItem fileItem = null;
- try {
- final List uploadedItems = upload.parseRequest( request );
- // Only one file upload at once is supported. If there are multiple files, take
- // the first one and ignore other
- if ( uploadedItems.size() > 0 ) {
- fileItem = ( FileItem )uploadedItems.get( 0 );
- // Don't check for file size 0 because this prevents uploading new empty office xp documents
- // which have a file size of 0.
- if( !fileItem.isFormField() ) {
- fileUploadStorageitem.setFileInputStream( fileItem.getInputStream() );
- fileUploadStorageitem.setContentType(fileItem.getContentType());
- }
- }
- } catch( final FileUploadException e ) {
- fileUploadStorageitem.setException(e);
- } catch( final Exception e ) {
- fileUploadStorageitem.setException(e);
- }
- }
- }
-
- /**
- * Applies custom configuration parameters specified by the
- * user.
- * @param upload The upload handler to which the config is applied.
- */
- private void applyConfiguration( final ServletFileUpload upload ) {
- upload.setFileSizeMax( getConfiguration().getFileSizeMax() );
- upload.setSizeMax( getConfiguration().getSizeMax() );
- }
-
- /**
- * Treats the request as a get request which is triggered by the
- * browser to retrieve the progress state. Gets the registered
- * {@link FileUploadListener} from the given {@link FileUploadStorageItem}
- * to check the current progress. The result is written to the response
- * in an XML format.
- * <br>
- * <b>Note:</b> It is important that a valid response is written in any case
- * to let the Browser know, when polling can be stopped.
- * @param uploadProcessId
- */
- private void handleUpdateProgress( final FileUploadStorageItem fileUploadStorageitem, final String uploadProcessId )
- throws IOException
- {
- final HttpServletResponse response = RWT.getResponse();
- final PrintWriter out = response.getWriter();
-
- final StringBuffer buffy = new StringBuffer( XML_HEAD );
- long bytesRead = 0;
- long contentLength = 0;
- // Check to see if we've created the listener object yet
- response.setContentType( "text/xml" );
- response.setHeader( "Cache-Control", "no-cache" );
-
- if( fileUploadStorageitem != null ) {
-
- if ( uploadProcessId != null && uploadProcessId.equals( fileUploadStorageitem.getUploadProcessId() )) {
-
- // Get the meta information
- bytesRead = fileUploadStorageitem.getBytesRead();
- contentLength = fileUploadStorageitem.getContentLength();
- /*
- * XML Response Code
- */
- buffy.append( "<bytes_read>" );
- buffy.append( bytesRead );
- buffy.append( "</bytes_read><content_length>" );
- buffy.append( contentLength );
- buffy.append( "</content_length>" );
- // Check to see if we're done
- // Even files with a size of 0 have a content length > 0
- if( contentLength != 0 ) {
- if( bytesRead == contentLength ) {
- buffy.append( "<finished />" );
- } else {
- // Calculate the percent complete
- buffy.append( "<percent_complete>" );
- buffy.append( ( 100 * bytesRead / contentLength ) );
- buffy.append( "</percent_complete>" );
- }
- } else {
- // Contentlength should not be 0, however, send finished to make sure
- // the Browser side polling stops.
- buffy.append( "<finished />" );
- }
- } else {
- //System.out.println("No match: " + uploadProcessId + " " + fileUploadStorageitem.getUploadProcessId());
- // if the processId doesn't match, return nothing
- // which causes the client script to send another
- // request after waiting. This could happen,
- // if the first GET-request was send, before the
- // Upload-POST request arrived.
- }
-
- } else {
- // if fileUploadStorageitem is null, the upload widget is disposed
- // return "finished" to stop monitoring
- buffy.append( "<finished />" );
- }
-
- buffy.append( "</response>" );
- out.println( buffy.toString() );
- out.flush();
- out.close();
- }
-
- /**
- * Registers this service handler. This method should be called only once.
- */
- public static void register() {
- final FileUploadServiceHandler instance = new FileUploadServiceHandler();
- final String serviceHandlerId = getServiceHandlerId();
- RWT.getServiceManager().registerServiceHandler(serviceHandlerId, instance);
- }
-
- /**
- * Returns a unique id for this service handler class.
- */
- private static String getServiceHandlerId() {
- final String serviceHandlerId = FileUploadServiceHandler.class.getName();
- return serviceHandlerId;
- }
-
- /**
- * Builds a url which points to the service handler and encodes the given parameters
- * as url parameters.
- */
- public static String getUrl(final String widgetId) {
- final StringBuffer url = new StringBuffer();
- url.append(URLHelper.getURLString(false));
-
- URLHelper.appendFirstParam(url, REQUEST_PARAM, getServiceHandlerId());
- URLHelper.appendParam(url, REQUEST_WIDGET_ID, widgetId);
-
- // convert to relative URL
- final int firstSlash = url.indexOf( "/" , url.indexOf( "//" ) + 2 ); // first slash after double slash of "http://"
- url.delete( 0, firstSlash ); // Result is sth like "/rap?custom_service_handler..."
- return RWT.getResponse().encodeURL(url.toString());
- }
-
- /**
- * Returns a configuration facade.
- */
- public static IUploadConfiguration getConfiguration() {
- return uploadConfiguration;
- }
-}