/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.web.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.pentaho.platform.api.engine.IPluginManager;
import org.pentaho.platform.api.engine.PluginBeanException;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.util.UUIDUtil;
import org.pentaho.platform.web.servlet.messages.Messages;
import org.safehaus.uuid.UUID;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
public class PluggableUploadFileServlet extends HttpServlet implements Servlet {
private static final long serialVersionUID = -1575521113175397124L;
protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
IOException {
try {
IUploadFileServletPlugin uploaderPlugin = getUploaderBean( getDispatchKey( request ), response );
if ( uploaderPlugin == null ) {
return;
}
response.setContentType( "text/plain" ); //$NON-NLS-1$
FileItem uploadItem = getFileItem( request, uploaderPlugin.getMaxFileSize() );
if ( uploadItem == null ) {
response.getWriter().write(
Messages.getInstance().getErrorString( "PluggableUploadFileServlet.ERROR_0001_NO_FILE_TO_UPLOAD" ) ); //$NON-NLS-1$
return;
}
String path = PentahoSystem.getApplicationContext().getSolutionPath( uploaderPlugin.getTargetFolder() );
File pathDir = new File( path );
// create the path if it doesn't exist yet
if ( !pathDir.exists() ) {
pathDir.mkdirs();
}
if ( uploadItem.getSize() + getFolderSize( pathDir ) > uploaderPlugin.getMaxFolderSize() ) {
response.getWriter().write(
Messages.getInstance().getErrorString( "PluggableUploadFileServlet.ERROR_0004_FOLDER_SIZE_LIMIT_REACHED" ) ); //$NON-NLS-1$
return;
}
UUID id = UUIDUtil.getUUID();
String filename = id.toString() + uploaderPlugin.getFileExtension();
File outFile = new File( path, filename );
if ( doesFileExists( outFile ) ) {
response.getWriter().write(
Messages.getInstance().getErrorString( "PluggableUploadFileServlet.ERROR_0002_FILE_ALREADY_EXIST" ) ); //$NON-NLS-1$
return;
}
InputStream fileInputStream = uploadItem.getInputStream();
FileOutputStream outputStream = new FileOutputStream( outFile );
try {
IOUtils.copy( fileInputStream, outputStream );
} finally {
if ( outputStream != null ) {
outputStream.close();
}
if ( fileInputStream != null ) {
fileInputStream.close();
}
}
uploaderPlugin.onSuccess( outFile.getAbsolutePath(), response );
} catch ( Exception e ) {
response.getWriter().write(
Messages.getInstance().getErrorString(
"PluggableUploadFileServlet.ERROR_0005_UNKNOWN_ERROR", e.getLocalizedMessage() ) ); //$NON-NLS-1$
}
}
protected IUploadFileServletPlugin getUploaderBean( String uploaderBeanId, HttpServletResponse response )
throws PluginBeanException, IOException {
if ( StringUtils.isEmpty( uploaderBeanId ) ) {
response.getWriter().write(
Messages.getInstance().getErrorString( "PluggableUploadFileServlet.ERROR_0006_NO_UPLOADER_FOUND" ) ); //$NON-NLS-1$
return null;
}
IPluginManager pluginManager = PentahoSystem.get( IPluginManager.class );
if ( !pluginManager.isBeanRegistered( uploaderBeanId ) ) {
response.getWriter().write(
Messages.getInstance().getErrorString(
"PluggableUploadFileServlet.ERROR_0008_NO_UPLOADER_BY_ID", uploaderBeanId ) ); //$NON-NLS-1$
return null;
}
Object uploaderBean = pluginManager.getBean( uploaderBeanId );
if ( !( uploaderBean instanceof IUploadFileServletPlugin ) ) {
response.getWriter().write(
Messages.getInstance().getErrorString(
"PluggableUploadFileServlet.ERROR_0007_UPLOADER_WRONG_TYPE", IUploadFileServletPlugin.class.getName() ) ); //$NON-NLS-1$
return null;
}
IUploadFileServletPlugin uploaderPlugin = (IUploadFileServletPlugin) uploaderBean;
return uploaderPlugin;
}
@SuppressWarnings( "unchecked" )
private FileItem getFileItem( HttpServletRequest request, long maxFileSize ) throws FileUploadException {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload( factory );
upload.setFileSizeMax( maxFileSize );
List items = upload.parseRequest( request );
Iterator it = items.iterator();
while ( it.hasNext() ) {
FileItem item = (FileItem) it.next();
if ( !item.isFormField() ) {
return item;
}
}
return null;
}
private long getFolderSize( File folder ) {
long foldersize = 0;
File[] filelist = folder.listFiles();
for ( int i = 0; i < filelist.length; i++ ) {
if ( filelist[i].isDirectory() ) {
foldersize += getFolderSize( filelist[i] );
} else {
foldersize += filelist[i].length();
}
}
return foldersize;
}
private boolean doesFileExists( File file ) {
return file.exists();
}
/**
* Returns the dispatch key for this request. This name is the part of the request path beyond the servlet base path.
* I.e. if the PluggableUploadFileServlet is mapped to the "/upload" context in web.xml, then this method will return
* "testuploader" given a request to "http://localhost:8080/pentaho/upload/testuploader".
*
* @return the part of the request url used to dispatch the request
*/
public String getDispatchKey( HttpServletRequest request ) {
// path info will give us what we want with
String requestPathInfo = request.getPathInfo();
if ( requestPathInfo.startsWith( "/" ) ) { //$NON-NLS-1$
requestPathInfo = requestPathInfo.substring( 1 );
}
return requestPathInfo;
}
}