package org.entermedia.upload;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openedit.Data;
import org.openedit.data.Searcher;
import org.openedit.repository.ContentItem;
import org.openedit.repository.InputStreamItem;
import org.openedit.util.DateStorageUtil;
import com.openedit.OpenEditException;
import com.openedit.WebPageRequest;
import com.openedit.page.Page;
import com.openedit.page.manage.PageManager;
import com.openedit.users.User;
import com.openedit.util.OutputFiller;
import com.openedit.util.PathUtilities;
import com.openedit.util.ZipUtil;
public class UploadRequest implements ProgressListener
{
private static final Log log = LogFactory.getLog(UploadRequest.class);
protected List fieldUploadItems;
protected PageManager fieldPageManager;
protected File fieldRoot;
protected ZipUtil fieldZipUtil;
protected OutputFiller fieldFiller;
protected String fieldUploadId;
protected String fieldCatalogId;
protected String fieldUserName;
protected long fieldSoFar;
public UploadRequest()
{
// TODO Auto-generated constructor stub
}
public long getSoFar()
{
return fieldSoFar;
}
public void setSoFar(long inSoFar)
{
fieldSoFar = inSoFar;
}
public String getUserName()
{
return fieldUserName;
}
public void setUserName(String inUserName)
{
fieldUserName = inUserName;
}
public String getCatalogId()
{
return fieldCatalogId;
}
public void setCatalogId(String inCatalogId)
{
fieldCatalogId = inCatalogId;
}
public String getUploadId()
{
return fieldUploadId;
}
public void setUploadId(String inUploadId)
{
fieldUploadId = inUploadId;
}
public Map getUploadCache()
{
if (fieldUploadCache == null)
{
fieldUploadCache = new HashMap();
}
return fieldUploadCache;
}
public void setUploadCache(Map inUploadCache)
{
fieldUploadCache = inUploadCache;
}
protected Map fieldUploadCache;
protected Searcher fieldUploadQueueSearcher;
public Searcher getUploadQueueSearcher()
{
return fieldUploadQueueSearcher;
}
public void setUploadQueueSearcher(Searcher inUploadQueueSearcher)
{
fieldUploadQueueSearcher = inUploadQueueSearcher;
}
public OutputFiller getFiller()
{
if (fieldFiller == null)
{
fieldFiller = new OutputFiller();
}
return fieldFiller;
}
public void setFiller(OutputFiller inFiller)
{
fieldFiller = inFiller;
}
public void addUploadItem(FileUploadItem inItem)
{
getUploadItems().add(inItem);
}
public List getUploadItems()
{
if (fieldUploadItems == null)
{
fieldUploadItems = new ArrayList();
}
return fieldUploadItems;
}
public void setUploadItems(List inUploadItems)
{
fieldUploadItems = inUploadItems;
}
public String getPathFor(String home, FileUploadItem inItem, WebPageRequest inReq) throws OpenEditException
{
String path = inReq.getContentProperty("path");
if( path == null )
{
String allow = inReq.findValue("allowspecifiedpath");
if( Boolean.parseBoolean(allow))
{
path = inReq.getRequestParameter("path");
if( path == null)
{
path = inItem.get("path");
}
}
}
if (path == null )
{
long utime = System.currentTimeMillis();
path = "/WEB-INF/temp/uploading/" + inReq.getUserName() + "/tmp" + utime + "/" + inItem.getName();
//throw new OpenEditException("No path passed in with the upload");
}
if( home != null && home.length() > 0 && path.startsWith(home))
{
path = path.substring(home.length());
}
String finalpath = null;
//TODO: Ok so on Windows we get passed in \\ in the file name
String name = inItem.getName();
name = name.replace('\\','/');
name = PathUtilities.extractFileName(name);
// name = name.replaceAll(" ","");
String targetname = inReq.getRequestParameter("targetname");
if(targetname != null)
{
targetname = targetname.replace('\\', '/'); //Not sure I need to do this
name = targetname;
}
if( path.endsWith("/"))
{
finalpath = path + name;
}
else
{
Page page = getPageManager().getPage(path);
if ( page.isFolder() ) //upload to an exising folder
{
finalpath = path + "/" + name;
}
else
{
finalpath = path;
}
}
return finalpath;
}
public PageManager getPageManager()
{
return fieldPageManager;
}
public void setPageManager(PageManager inPageManager)
{
fieldPageManager = inPageManager;
}
public void saveFile(FileUploadItem inItem, String inHome, WebPageRequest inReq) throws OpenEditException
{
/**
* inPath is full filename
* @param inProps
*/
//From now on we are going to assume people always upload to a directory
String inPath = getPathFor(inHome, inItem, inReq);
if( inPath == null)
{
return; //already saved?
}
if (inPath.indexOf("..") > -1)
{
throw new OpenEditException("Illegal path name");
}
final String path = PathUtilities.resolveRelativePath( inPath, "/");
saveFileAs(inItem, path, inReq.getUser());
}
public void saveFileAs(FileUploadItem inItem, final String path, User inUser)
throws OpenEditException
{
Page page = getPageManager().getPage( path, true );
InputStreamItem revision = new InputStreamItem();
// final Date lastModified = new Date();
if ( inUser == null)
{
throw new IllegalArgumentException("No user logged in");
}
revision.setAuthor( inUser.getUserName() );
revision.setType( ContentItem.TYPE_ADDED );
revision.setMessage( "Uploaded file");
revision.setPath(path);
InputStream input = null;
try
{
FileItem item = inItem.getFileItem();
if (item instanceof DiskFileItem)
{
DiskFileItem fileItem = (DiskFileItem) item;
if( fileItem.getHeaders() != null )
{
if ("gzip".equals(fileItem.getHeaders().getHeader("Content-Encoding")))
{
input = new GZIPInputStream(fileItem.getInputStream());
}
}
}
if (input == null)
{
input = item.getInputStream();
}
}
catch ( IOException ex)
{
throw new OpenEditException(ex);
}
revision.setInputStream(input);
page.setContentItem(revision);
log.info("Saved " + page);
//OutputStreamItem item = new OutputStreamItem(page.getPath());
// String offset = inItem.get("offset");
// if( offset != null)
// {getUploadItems
// item.setSeek(Long.parseLong(offset));
// }
//page.setContentItem(item);
getPageManager().putPage(page); //FileReposityory will set the item.setOutputstream for us
inItem.setSavedPage(page);
}
public List unzipFiles(boolean inForceUnzip) throws OpenEditException
{
List unzippedPages = new ArrayList();
PageManager pm = getPageManager();
for (Iterator iterator = getUploadItems().iterator(); iterator.hasNext();)
{
FileUploadItem item = (FileUploadItem) iterator.next();
Page page = pm.getPage(item.getSavedPage().getPath());
if ( page.getPath().toLowerCase().endsWith(".zip"))
{
List unzippedFiles = new ArrayList();
String ok = (String)item.get("unzip");
if ( inForceUnzip || "checked".equals(ok) || Boolean.parseBoolean(ok))
{
log.info("Unzipping " + page.getPath());
File in = new File( page.getContentItem().getAbsolutePath() );//getPageManager().getRepository().getStub(inPath)//new File( getRoot(), page.getContentItem().getPath() );
try
{
unzippedFiles.addAll(getZipUtil().unzip(in, in.getParentFile()));
}
catch (Exception ex)
{
log.error("Could not unzip : " + in.getAbsolutePath());
log.error( ex );
return unzippedPages;
}
getPageManager().removePage(page);
for (Iterator iterator2 = unzippedFiles.iterator(); iterator2.hasNext();) {
File file = (File) iterator2.next();
String upath = file.getAbsolutePath();
upath = upath.substring(in.getParentFile().getAbsolutePath().length() + 1);
upath = page.getDirectory() + "/" + upath;
Page unz = getPageManager().getPage(upath);
unzippedPages.add(unz);
}
}
}
}
return unzippedPages;
}
public File getRoot()
{
return fieldRoot;
}
public void setRoot(File inRoot)
{
fieldRoot = inRoot;
}
public ZipUtil getZipUtil()
{
if( fieldZipUtil == null)
{
fieldZipUtil = new ZipUtil();
}
return fieldZipUtil;
}
public void setZipUtil(ZipUtil inZipUtil)
{
fieldZipUtil = inZipUtil;
}
public Page saveFirstFileAs(String inPath, User inUser) throws OpenEditException
{
FileUploadItem item = getFirstItem();
saveFileAs(item, inPath, inUser);
return item.getSavedPage();
}
public FileUploadItem getFirstItem()
{
for (Iterator iterator = getUploadItems().iterator(); iterator.hasNext();)
{
FileUploadItem item = (FileUploadItem) iterator.next();
return item;
}
return null;
}
public FileUploadItem getUploadItem(int inI)
{
for (Iterator iterator = getUploadItems().iterator(); iterator.hasNext();)
{
FileUploadItem item = (FileUploadItem) iterator.next();
if( item.getCount() == inI)
{
return item;
}
}
return null;
}
public FileUploadItem getUploadItemByName(String inName)
{
for (Iterator iterator = getUploadItems().iterator(); iterator.hasNext();)
{
FileUploadItem item = (FileUploadItem) iterator.next();
if( inName.equals(item.getFileItem().getFieldName()))
{
return item;
}
}
return null;
}
/**
* Put breakpoints here to slow down the upload
*
*/
public void update(long inBytesRead, long inContentLength, int inItemNumber)
{
if( getUploadId() == null )
{
return;
}
//inItemNumber = inItemNumber - 1;
Data uploaddata = loadUploadData(inItemNumber);
String existing = uploaddata.get("date");
boolean update = true;
if( existing != null)
{
Date saved = DateStorageUtil.getStorageUtil().parseFromStorage(existing);
Date recently = new Date(System.currentTimeMillis() - 2000);
if( saved.before(recently))
{
update = true;
}
else
{
update = false;
}
}
//track on a per file basis
//long thechange = inBytesRead - fieldSoFar;
//fieldSoFar = inBytesRead;
String sofar = uploaddata.get("filesizeuploaded");
if( sofar == null )
{
sofar = "0";
}
//long saved = Long.parseLong( sofar ) + thechange;
uploaddata.setProperty("filesize", String.valueOf( inContentLength));
uploaddata.setProperty("filesizeuploaded", String.valueOf( inBytesRead ));
uploaddata.setProperty("date", DateStorageUtil.getStorageUtil().formatForStorage(new Date()));
if( inBytesRead == inContentLength)
{
uploaddata.setProperty("status", "complete");
update = true;
}
if(update)
{
//PRO tip: Put breakpoint here to slow down uploads
getUploadQueueSearcher().saveData(uploaddata, null);
log.info("updated: " + uploaddata.getId() + " " + uploaddata.get("filesizeuploaded") + " hash:" + uploaddata.hashCode() );
// try
// {
// Thread.sleep(1000);
// }
// catch(Exception ewx)
// {}
}
}
protected Data loadUploadData(int inItemNumber)
{
Data task = (Data)getUploadCache().get(inItemNumber);
if( task == null )
{
task = addRecentUpload(getCatalogId(), getUploadId() + "_" + inItemNumber);
task.setSourcePath("users/" + getUserName());
task.setName(getUploadId());
getUploadCache().put(inItemNumber, task);
}
return task;
}
protected Data addRecentUpload(String inCatId, String inUploadId)
{
Searcher searcher = getUploadQueueSearcher();
Data req = (Data)searcher.searchById(inUploadId);
if( req == null)
{
req= searcher.createNewData();
req.setId(inUploadId);
}
return req;
}
public void track(String inFieldName, String inContentType,String inFileName)
{
//create a record and loop over the records each time an update happens
}
}