Package ca.carleton.gcrc.upload

Source Code of ca.carleton.gcrc.upload.UploadServlet

/*
Copyright (c) 2010, Geomatics and Cartographic Research Centre, Carleton
University
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
- Neither the name of the Geomatics and Cartographic Research Centre,
   Carleton University nor the names of its contributors may be used to
   endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

$Id$
*/
package ca.carleton.gcrc.upload;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.FileCleanerCleanup;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.apache.commons.io.FileCleaningTracker;
import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;

import ca.carleton.gcrc.contributions.Contributions;
import ca.carleton.gcrc.contributions.ContributionsUtils;
import ca.carleton.gcrc.jdbc.JdbcConnections;
import ca.carleton.gcrc.progress.ProgressTracker;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.sql.Connection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

public class UploadServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  final protected Logger logger = Logger.getLogger(this.getClass());
 
  static final int DEFAULT_MAX_MEMORY_SIZE = 10 * 1024; // 10KB
  static final long DEFAULT_MAX_UPLOAD_SIZE = 10 * 1024 * 1024; // 10MB
 
  private int maxMemorySize = DEFAULT_MAX_MEMORY_SIZE;
  private long maxUploadSize = DEFAULT_MAX_UPLOAD_SIZE;
  private File fileItemTempDir = null;
  private DiskFileItemFactory fileItemfactory = null;
  private File repositoryDir = null;
  private Connection connection = null;
  private JdbcConnections connections = null;
  private Contributions contributions;

  private OnUploadedListener onUploadedListener = null;
 
  public UploadServlet() {
   
  }

  public void init(ServletConfig config) throws ServletException {
    super.init(config);
   
    // Figure out root file
    File rootFile = null;
    {
      if( null != config ) {
        if( null != config.getServletContext() ) {
          String realRoot = config.getServletContext().getRealPath(".");
          if( null != realRoot ) {
            rootFile = new File(realRoot);
          }
        }
      }
    }
   
    // Load up configuration information
    Properties props = new Properties();
    {
      File propFile = null;
      if( null != rootFile ) {
        propFile = new File(rootFile, "WEB-INF/upload.properties");
        if( false == propFile.exists()
         || false == propFile.isFile() ) {
          propFile = null;
        }
      }
      if( null != rootFile && null == propFile ) {
        propFile = new File(rootFile, "WEB-INF/upload.properties.default");
        if( false == propFile.exists()
         || false == propFile.isFile() ) {
          propFile = null;
        }
      }
      if( null == propFile ) {
        logger.error("Property file location can not be determined");
      } else {
        logger.info("Reading properties from "+propFile.getAbsolutePath());
        FileInputStream fis = null;
        try {
          fis = new FileInputStream(propFile);
          props.load(fis);
        } catch (Exception e) {
          logger.error("Unable to read properties from "+propFile.getAbsolutePath(),e);
        } finally {
          if( null != fis ) {
            try {
              fis.close();
            } catch (Exception e) {
              // Ignore
            }
          }
        }
      }
    }

    // Temp directory
    String tempDirName = props.getProperty("tempDir");
    if( null != tempDirName ) {
      fileItemTempDir = new File(tempDirName);
      if( false == fileItemTempDir.isAbsolute() ) {
        fileItemTempDir = new File(rootFile, fileItemTempDir.getPath());
      }
      logger.info("Temp directory is "+fileItemTempDir.getAbsolutePath());
    }

    // Repository directory (this is where files are sent to)
    String repositoryDirName = props.getProperty("repositoryDir");
    if( null != repositoryDirName ) {
      repositoryDir = new File(repositoryDirName);
      if( false == repositoryDir.isAbsolute() ) {
        repositoryDir = new File(rootFile, repositoryDir.getPath());
      }
    } else {
      repositoryDir = new File(rootFile, "."); // current dir
    }
    logger.info("Repository directory is "+repositoryDir.getAbsolutePath());
    if( false == repositoryDir.exists() ) {
      logger.error("Repository directory does not exist! "+repositoryDir.getAbsolutePath());
    } else if( false == repositoryDir.isDirectory() ) {
      logger.error(repositoryDir.getAbsolutePath()+" is not a directory!");
    }
   
    try {
      connections = JdbcConnections.connectionsFromServletContext(config.getServletContext());
      connection = connections.getDb();
    } catch (Exception e) {
      throw new ServletException("Error while connecting to database",e);
    }
    contributions = ContributionsUtils.createContibutionHandler(config, connection);
    if (null == contributions) {
      return;
    }
   
    // Load up follow-on task for file upload
    String onLoadClassName = props.getProperty("onUploadedListener");
    if( null != onLoadClassName ) {
      logger.info("Loading 'onLoad' class: "+onLoadClassName);
      Class<?> clazz = null;
      try {
        clazz = this.getClass().getClassLoader().loadClass(onLoadClassName);
      } catch (ClassNotFoundException e) {
        throw new ServletException("Unable to find specified class: "+onLoadClassName,e);
      }
      Class<? extends OnUploadedListener> onLoadTaskClass = null;
      try {
        onLoadTaskClass = clazz.asSubclass(OnUploadedListener.class);
      } catch (Exception e) {
        throw new ServletException(clazz.getName()+" does not implements "+OnUploadedListener.class.getName());
      }
      Constructor<? extends OnUploadedListener> constructorDefault = null;
      try {
        Class<?>[] parameters = new Class<?>[0];
        constructorDefault = onLoadTaskClass.getConstructor(parameters);
      } catch (Exception e) {
        // Ignore
        // throw new ServletException("Can not accept default constructor on "+clazz.getName(),e);
      }
      Constructor<? extends OnUploadedListener> constructorServletConfig = null;
      try {
        Class<?>[] parameters = new Class<?>[1];
        parameters[0] = ServletConfig.class;
        constructorServletConfig = onLoadTaskClass.getConstructor(parameters);
      } catch (Exception e) {
        // Ignore
        // throw new ServletException("Can not accept default constructor on "+clazz.getName(),e);
      }
      if( null != constructorServletConfig ) {
        try {
          Object[] params = new Object[1];
          params[0] = config;
          onUploadedListener = constructorServletConfig.newInstance(params);
        } catch (Exception e) {
          throw new ServletException("Unable to create an instance of "+clazz.getName()+" using ServletConfig",e);
        }
      } else if( null != constructorDefault ) {
        try {
          onUploadedListener = constructorDefault.newInstance((Object[])null);
        } catch (Exception e) {
          throw new ServletException("Unable to create an instance of "+clazz.getName()+" using default constructor",e);
        }
      } else {
        throw new ServletException("Class "+clazz.getName()+" must implement a constructor based on 'ServletConfig' or a default constructor");
      }
    }

    fileItemfactory = new DiskFileItemFactory();
    fileItemfactory.setSizeThreshold(maxMemorySize);
    if( null != fileItemTempDir ) {
      fileItemfactory.setRepository(fileItemTempDir);
    }
  }

  public void destroy() {
    FileCleaningTracker cleaner = FileCleanerCleanup.getFileCleaningTracker(this.getServletContext());
    if( null != cleaner ) {
      cleaner.exitWhenFinished();
    }
  }

  public synchronized int getMaxMemorySize() {
    return maxMemorySize;
  }

  public synchronized void setMaxMemorySize(int maxMemorySize) {
    this.maxMemorySize = maxMemorySize;
  }

  public synchronized long getMaxUploadSize() {
    return maxUploadSize;
  }

  public synchronized void setMaxUploadSize(long maxUploadSize) {
    this.maxUploadSize = maxUploadSize;
  }
 
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String paths[] = request.getRequestURI().split("/");
    String path = paths[ paths.length - 1 ];
   
    logger.info("UploadServlet "+path);

    if( "put".equalsIgnoreCase(path) ) {
      doFileUpload(request, response);
     
    } else {
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unknown request");
    }
  }

  private void doFileUpload(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String progressId = null;
    List<LoadedFile> loadedFiles = new Vector<LoadedFile>();
    Map<String,List<String>> parameterMap = new HashMap<String,List<String>>();
   
    try {
      // Check that we have a file upload request
      boolean isMultipart = ServletFileUpload.isMultipartContent(request);
     
      if ( false == isMultipart ) {
        throw new Exception("File upload must be a multi-part request");
      }
     
      UploadProgressListener listener = new UploadProgressListener();
     
      ServletFileUpload upload = new ServletFileUpload(fileItemfactory);
      upload.setSizeMax(maxUploadSize);
      upload.setProgressListener(listener);
     
      FileItemIterator iter = upload.getItemIterator(request);
      while (iter.hasNext()) {
          FileItemStream item = iter.next();
          String name = item.getFieldName();
          InputStream stream = item.openStream();
          if (item.isFormField()) {
            String value = Streams.asString(stream);

            logger.info("Upload "+name+":"+value);
           
            if( "progressId".equals(name) ) {
              progressId = value;
              listener.setProgressId(value);
            }
           
            // Add parameter to map
            List<String> paramList = parameterMap.get(name);
            if( null == paramList ) {
              paramList = new Vector<String>();
              parameterMap.put(name,paramList);
            }
            paramList.add(value);
           
          } else {
           
            LoadedFileImpl loadedFile = new LoadedFileImpl();
            loadedFile.setParameterName(name);

            // Get original filename
            String fileName = item.getName();
              if (fileName != null) {
                fileName = fileName.trim();
                if( 0 == fileName.length() ) {
                  fileName = null;
                } else {
                  fileName = FilenameUtils.getName(fileName);
                }
              }
             
              if( fileName != null ) {
                loadedFile.setOriginalFileName(fileName);
 
                listener.setFileName(fileName);
 
              logger.info("Upload file is "+fileName);
 
              // Figure out suffix
              String suffix = "";
              if( null != fileName ){
                String parts[] = fileName.split("\\.");
                if( parts.length > 1 ) {
                  suffix = "."+parts[ parts.length-1 ];
                }
              }
             
              // Create a name for this file
              File target = File.createTempFile("upl", suffix, repositoryDir);
              loadedFile.setFile(target);
             
              FileOutputStream fos = null;
            try {
              fos = new FileOutputStream(target);
              int b = stream.read();
              while( b >= 0) {
                fos.write(b);
                b = stream.read();
              }
            } catch (Exception e) {
              throw new Exception("Error while writing file "+target.getAbsolutePath());
            } finally {
              if( null != fos ) {
                try {
                  fos.close();
                } catch (Exception e) {
                  // Ignore
                }
              }
            }
          
            loadedFiles.add(loadedFile);
                logger.info("File written to "+target.getAbsolutePath());
              }
          }
      }
     
      // Run onLoad task
      JSONObject onLoadResults = null;
      if( null != onUploadedListener ) {
        onLoadResults = onUploadedListener.onLoad(progressId, loadedFiles, parameterMap, request.getUserPrincipal(), contributions);
      }
     
      // Mark that the progress on this is completed
      if( null != progressId ) {
        ProgressTracker.completeProgess(progressId, null);
      }
     
      // Return JSON object to acknowledge the upload
      {
        JSONObject obj = new JSONObject();
       
        if( null != progressId ) {
          obj.put("progressId", progressId);
        }
       
        if( loadedFiles.size() > 0 ) {
          JSONArray uploadedArray = new JSONArray();
          obj.put("uploaded", uploadedArray);
         
          Iterator<LoadedFile> itLoadedFile = loadedFiles.iterator();
          while( itLoadedFile.hasNext() ) {
            LoadedFile loadedFile = itLoadedFile.next();
           
            JSONObject fileObj = new JSONObject();
            fileObj.put("original", loadedFile.getOriginalFileName());
            fileObj.put("target", loadedFile.getFile().getName());
           
            uploadedArray.add(fileObj);
          }
        }
       
        // OnLoad results
        if( null != onLoadResults ) {
          obj.put("onLoadResults", onLoadResults);
        }
       
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/plain");
        response.setHeader("Cache-Control", "no-cache,must-revalidate");
        response.setDateHeader("Expires", (new Date()).getTime());
       
        OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream(),"UTF-8");
        obj.write(osw);
        osw.flush();
      }
    } catch (SizeLimitExceededException e) {
      reportError(response, HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e, loadedFiles, progressId);
    } catch (FileSizeLimitExceededException e) {
      reportError(response, HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e, loadedFiles, progressId);
    } catch (Exception e) {
      reportError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e, loadedFiles, progressId);
    }
  }
 
  private void reportError(HttpServletResponse response, int code, Throwable error, List<LoadedFile> loadedFiles, String progressId) throws IOException {
    // Figure out which file it choked on
    String fileName = "<unknown>";
    if( null != loadedFiles && loadedFiles.size() > 0 ) {
      fileName = loadedFiles.get(loadedFiles.size()-1).getOriginalFileName();
    }
   
    logger.info("Error loading file "+fileName,error);
   
    // Mark that the progress on this is completed
    if( null != progressId ) {
      ProgressTracker.completeProgess(progressId, error.getMessage());
    }
   
    if( null != error ) {
      response.sendError(code, error.getMessage());
    } else {
      response.sendError(code);
    }
  }
}
TOP

Related Classes of ca.carleton.gcrc.upload.UploadServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.