In kind of a hurry, I put together a fix for OLIO-40 for the Java kit.
There are a couple of choices made without the best of confidence.
Without thorough testing, we'll never know we're dealing with the right
choice.
I'm trying to conceptually stick with the original idea of processing
the file uploads without saving to any file. I think it is a great idea,
but presents a good amount of challenges. So we will insert a record
with whatever we have in the request before the first uploaded file - in
one transaction, in order to obtain the key (user or event id). Then we
save the image into place and process the thumbnail at the same time.
The complete record will be written in an update, complete with image
locations. The address will be created and linked at update time (after
the initial insert) just to be sure all the address information has
arrived, and also to be sure we don't create the address twice and call
the geocoder twice.
If this strategy doesn't work, the alternative is to do the address and
geocoder in the first create. We need to make sure the sequence the
field arrives is so that the images and literature arrive last. The
update needs to be narrowed down to just the image file (for which we
don't have the file name at create) in the update - just like how we do
it in php.
Since I'm not going to be available for a week, I have to leave the
patch up here for review and comments. Please feel free to test it out
if you have the time. Let me know any fixes you make. I'll resume
testing after I'm back. Again, any comments about this initial code as
well as the strategy taken is most welcome.
Regards,
-Akara
Index: ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/fileupload/FileUploadHandler.java
===================================================================
--- ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/fileupload/FileUploadHandler.java (revision 822866)
+++ ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/fileupload/FileUploadHandler.java Fri Oct 16 19:53:40 PDT 2009
@@ -27,34 +27,24 @@
*/
package org.apache.olio.webapp.fileupload;
-import org.apache.olio.webapp.util.fs.FileSystem;
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileItemStream;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.olio.webapp.controller.WebConstants;
import org.apache.olio.webapp.util.ServiceLocator;
import org.apache.olio.webapp.util.WebappConstants;
-import org.apache.olio.webapp.controller.WebConstants;
-import org.apache.olio.webapp.model.Person;
-import org.apache.olio.webapp.security.SecurityHandler;
import org.apache.olio.webapp.util.WebappUtil;
-import java.io.IOException;
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.logging.Logger;
-import java.util.logging.Level;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import org.apache.olio.webapp.util.fs.FileSystem;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import java.io.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
-import org.apache.commons.fileupload.FileItemIterator;
-import org.apache.commons.fileupload.FileItemStream;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-
/**
* This class uses Apache Commons FileUpload to parse the multi-part mime that is sent via the HttpServletRequest InputStream.
* This class also relies on Faces to populate the fileUploadStatus in this Backing Bean on each request.
@@ -66,7 +56,9 @@
private static Logger logger = Logger.getLogger(FileUploadHandler.class.getName());
private FileUploadStatus fileUploadStatus = null;
+ private FileItemIterator itemIter;
+ private Hashtable<String, String> requestParams;
-
+
/**
* Default location of upload directory is /domain_dir/lib/upload, unless the Sun Appserver system property exits, then it will
* use the domain's lib/upload directory instead
@@ -157,12 +149,13 @@
}
/**
- * Invoke the fileupload process that reads the input from the HttpServletRequest inputStream. Since this
- * component accesses the HttpServletRequest directly, this component currently may not work from within a portlet.
- * This method assumes that the fileUploadStatus will be set using the managed property functionality of a backing bean.
- * This relationship is specified in the faces-config.xml file. This method is accessed through the Shale-remoting dynamic framework.
+ * Handles the initial fields up to the first upload field. This will
+ * allow creating the database entry and obtaining the auto-generated
+ * ids.
+ * @return A hash table with the initial field values
*/
- public Hashtable<String, String> handleFileUpload(HttpServletRequest request, HttpServletResponse response) {
+ public Hashtable<String, String> getInitialParams(HttpServletRequest request, HttpServletResponse response) {
+
// print out header for
Enumeration enumx = request.getHeaderNames();
String key = "";
@@ -172,10 +165,9 @@
listx += "\n" + key + ":" + request.getHeader(key);
}
logger.fine("Incoming Header Item:" + listx);
-
- // enable progress bar (this managed bean that is in the session could be comp specific, but I can't create the component specific
+ // enable progress bar (this managed bean that is in the session could be comp specific, but I can't create the component specific
// session object until I have the components name. For now use static key through backing bean).
- // Use session to allow the monitoring of the fileupload based
+ // Use session to allow the monitoring of the fileupload based
HttpSession session = request.getSession();
FileUploadStatus status = new FileUploadStatus();
@@ -203,87 +195,115 @@
// Now we should have the componentsName and upload directory to setup remaining upload of file items
String compName = htUpload.get(FileUploadUtil.COMPONENT_NAME);
status.setName(compName);
- // get directory to dump file into
- String serverLocationDir = htUpload.get(compName + "_" + FileUploadUtil.SERVER_LOCATION_DIR);
- logger.fine("\n*** locationDir=" + serverLocationDir);
+ // Parse the request and return list of "FileItem" whle updating status
+ FileItemIterator iter = upload.getItemIterator(request);
+
+ status.setReadingComplete();
+
+ while (iter.hasNext()) {
+ FileItemStream item = iter.next();
+ if (item.isFormField()) {
+ // handle a form item being uploaded
+ String itemName = item.getFieldName();
+
+ // process form(non-file) item
+ int size = formItemFound(item, htUpload);
+ updateSessionStatus(itemName, size);
+
+ logger.fine("Form field item:" + itemName);
+
+ } else {
+ // At the first find of an uploaded file, stop.
+ // We need to insert our record first in order
+ // to find the id.
+ break;
+ }
+ }
+ itemIter = iter;
+ } catch (Exception e) {
+ status.setUploadError("FileUpload didn't complete successfully. Exception received:" + e.toString());
+ logger.log(Level.SEVERE, "file.upload.exception", e);
+ }
+ }
+ fileUploadStatus = status;
+ requestParams = htUpload;
+ return htUpload;
+ }
+
+
+
+ /**
+ * Invoke the fileupload process that reads the input from the HttpServletRequest inputStream. Since this
+ * component accesses the HttpServletRequest directly, this component currently may not work from within a portlet.
+ * This method assumes that the fileUploadStatus will be set using the managed property functionality of a backing bean.
+ * This relationship is specified in the faces-config.xml file. This method is accessed through the Shale-remoting dynamic framework.
+ */
+ public Hashtable<String, String> handleFileUpload(String id, HttpServletRequest request, HttpServletResponse response) {
+
- File fileDir = null;
+ File fileDir = null;
+ String compName = requestParams.get(FileUploadUtil.COMPONENT_NAME);
+ String serverLocationDir = requestParams.get(compName + "_" + FileUploadUtil.SERVER_LOCATION_DIR);
+ logger.fine("\n*** locationDir=" + serverLocationDir);
- if (serverLocationDir == null) {
- // ??? need to fix incase other than glassfish
- // set to default dir location for glassfish
- serverLocationDir = System.getProperty("com.sun.aas.instanceRoot");
- if (serverLocationDir != null) {
- serverLocationDir = WebappConstants.WEBAPP_IMAGE_DIRECTORY;
- fileDir = new File(serverLocationDir);
- fileDir.mkdirs();
- } else {
- // use the standard tmp directory
- logger.fine("\n*** other default locationDir=" + serverLocationDir);
+ if (serverLocationDir == null) {
+ // ??? need to fix incase other than glassfish
+ // set to default dir location for glassfish
+ serverLocationDir = System.getProperty("com.sun.aas.instanceRoot");
+ if (serverLocationDir != null) {
+ serverLocationDir = WebappConstants.WEBAPP_IMAGE_DIRECTORY;
+ fileDir = new File(serverLocationDir);
+ fileDir.mkdirs();
+ } else {
+ // use the standard tmp directory
+ logger.fine("\n*** other default locationDir=" + serverLocationDir);
- //fileDir = (File) request.getAttribute("javax.servlet.context.tempdir");
- // we don't need the tmp directory since we are avoiding writing twice - once to /tmp and then to filestore
- // pick this up from the system environment(or web.xml) that WebappUtil sets
- serverLocationDir = WebappConstants.WEBAPP_IMAGE_DIRECTORY;
- serverLocationDir = fileDir.toString();
- }
- } else {
- // make sure directory exists, don't create automatically for security reasons
- fileDir = new File(serverLocationDir);
- }
+ //fileDir = (File) request.getAttribute("javax.servlet.context.tempdir");
+ // we don't need the tmp directory since we are avoiding writing twice - once to /tmp and then to filestore
+ // pick this up from the system environment(or web.xml) that WebappUtil sets
+ serverLocationDir = WebappConstants.WEBAPP_IMAGE_DIRECTORY;
+ serverLocationDir = fileDir.toString();
+ }
+ } else {
+ // make sure directory exists, don't create automatically for security reasons
+ fileDir = new File(serverLocationDir);
+ }
- // make sure dir exists and is writable
- if (fileDir == null || !fileDir.isDirectory() || !fileDir.canWrite()) {
- // error, directory doesn't exist or isn't writable
+ // make sure dir exists and is writable
+ if (fileDir == null || !fileDir.isDirectory() || !fileDir.canWrite()) {
+ // error, directory doesn't exist or isn't writable
- status.setUploadError("Directory \"" + fileDir.toString() + "\" doesn't exist!");
+ fileUploadStatus.setUploadError("Directory \"" + fileDir.toString() + "\" doesn't exist!");
- logger.log(Level.SEVERE, "directory.inaccessable", fileDir.toString());
- return null;
- }
+ logger.log(Level.SEVERE, "directory.inaccessable", fileDir.toString());
+ return null;
+ }
-
- // Parse the request and return list of "FileItem" whle updating status
- FileItemIterator iter = upload.getItemIterator(request);
-
- status.setReadingComplete();
-
- FileItemStream item = null;
- String itemName = null;
-
- while (iter.hasNext()) {
- item = iter.next();
+ try {
+ while (itemIter.hasNext()) {
+ FileItemStream item = itemIter.next();
- if (item.isFormField()) {
- // handle a form item being uploaded
+ if (item.isFormField()) {
+ // handle a form item being uploaded
- itemName = item.getFieldName();
+ String itemName = item.getFieldName();
- // process form(non-file) item
+ // process form(non-file) item
- int size = formItemFound(item, htUpload);
+ int size = formItemFound(item, requestParams);
- updateSessionStatus(itemName, size);
+ updateSessionStatus(itemName, size);
- logger.fine("Form field item:" + itemName);
+ logger.fine("Form field item:" + itemName);
- } else {
+ } else {
- String username = htUpload.get(WebConstants.SUBMITTER_USER_NAME_PARAM);
- if (username == null) {
- Person person = SecurityHandler.getInstance().getLoggedInPerson(request);
- if (person != null) {
- username = person.getUserName();
+ fileItemFound(item, requestParams, serverLocationDir, id);
- }
- }
+ }
+ }
- fileItemFound(item, htUpload, serverLocationDir, username);
- }
- }
-
- // put upload to 100% to handle rounding errors in status calc
+ // put upload to 100% to handle rounding errors in status calc
- status.setUploadComplete();
- logger.fine("Final session status - " + status);
+ fileUploadStatus.setUploadComplete();
+ logger.fine("Final session status - " + fileUploadStatus);
- } catch (Exception e) {
+ } catch (Exception e) {
- status.setUploadError("FileUpload didn't complete successfully. Exception received:" + e.toString());
+ fileUploadStatus.setUploadError("FileUpload didn't complete successfully. Exception received:" + e.toString());
- logger.log(Level.SEVERE, "file.upload.exception", e);
- }
+ logger.log(Level.SEVERE, "file.upload.exception", e);
+ }
+ return requestParams;
- }
+ }
- return htUpload;
- }
/**
* Handle upload of a standard form item
@@ -336,15 +356,10 @@
* @param serverLocationDir The Status Hashtable that contains the items that have been uploaded for post-processing use
*/
protected void fileItemFound(FileItemStream item, Hashtable<String, String> htUpload,
- String serverLocationDir, String user) throws Exception {
- if (user == null) {
- user = "guest";
- }
+ String serverLocationDir, String id) throws Exception {
+
String fileLocation = null;
String fileName = item.getName();
- //issue is that the same filename on client machine is being used on mastermachine. this could lead to conflicts.
- //use the username since is unique for image name. retrieve this from the Hashtable.
- String username = htUpload.get(WebConstants.USER_NAME_PARAM);
if (fileName != null && !fileName.equals("")) {
// see if IE on windows which send full path with item, but just filename
@@ -364,45 +379,35 @@
logger.fine("Have full path, need to truncate \n" + item.getName() + "\n" + fileName);
}
fileLocation = serverLocationDir + File.separator + fileName;
- DateFormat dateFormat = new SimpleDateFormat("MMMMddyyyy_hh_mm_ss");
- Date date = null;
String thumbnailName;
- String thumbnailLocation;
String ext = WebappUtil.getFileExtension(fileName);
if (item.getFieldName().equals(WebConstants.UPLOAD_PERSON_IMAGE_PARAM)) {
- fileName = "p" + username;
- thumbnailName = fileName + "_thumb" + ext;
- thumbnailLocation = serverLocationDir + "/" + thumbnailName;
+ fileName = "P" + id;
+ thumbnailName = fileName + 'T' + ext;
// Append the extension
fileName += ext;
- fileLocation = serverLocationDir + "/" + fileName;
- writeWithThumbnail(item, fileLocation, thumbnailLocation);
+ writeWithThumbnail(item, fileName, thumbnailName);
+ htUpload.put(WebConstants.UPLOAD_PERSON_IMAGE_PARAM, fileName);
htUpload.put(WebConstants.UPLOAD_PERSON_IMAGE_THUMBNAIL_PARAM, thumbnailName);
} else if (item.getFieldName().equals(WebConstants.UPLOAD_PERSON_IMAGE_THUMBNAIL_PARAM)) {
- fileName = "p" + username + "_t" + ext;
- fileLocation = serverLocationDir + "/" + fileName;
- write(item, fileLocation);
+ fileName = "P" + id + "T" + ext;
+ write(item, fileName);
htUpload.put(WebConstants.UPLOAD_PERSON_IMAGE_THUMBNAIL_PARAM, fileName);
} else if (item.getFieldName().equals(WebConstants.UPLOAD_EVENT_IMAGE_PARAM)) {
- date = new Date();
//String submitter = htUpload.get(WebConstants.SUBMITTER_USER_NAME_PARAM);
- fileName = "e" + user + dateFormat.format(date);
- thumbnailName = fileName + "_thumb" + ext;
- thumbnailLocation = serverLocationDir + "/" + thumbnailName;
+ fileName = "E" + id;
+ thumbnailName = fileName + 'T' + ext;
fileName += ext;
- fileLocation = serverLocationDir + "/" + fileName;
- writeWithThumbnail(item, fileLocation, thumbnailLocation);
+ writeWithThumbnail(item, fileName, thumbnailName);
+ htUpload.put(WebConstants.UPLOAD_EVENT_IMAGE_PARAM, fileName);
htUpload.put(WebConstants.UPLOAD_EVENT_IMAGE_THUMBNAIL_PARAM, thumbnailName);
} else if (item.getFieldName().equals("eventThumbnail")) {
- date = new Date();
- fileName = "e" + user + dateFormat.format(date) + "_t" + ext;
- fileLocation = serverLocationDir + "/" + fileName;
- write(item, fileLocation);
+ fileName = "E" + id + 'T' + ext;
+ write(item, fileName);
htUpload.put(WebConstants.UPLOAD_EVENT_IMAGE_THUMBNAIL_PARAM, fileName);
} else if (item.getFieldName().equals("upload_event_literature")) {
- date = new Date();
- fileName = "e" + user + dateFormat.format(date) + ext;
+ fileName = "E" + id + 'L' + ext;
fileLocation = serverLocationDir + "/" + fileName;
write(item, fileLocation);
htUpload.put(WebConstants.UPLOAD_LITERATURE_PARAM, fileName);
@@ -431,7 +436,8 @@
* If the post processing method wants to provide a custom response, the method can call the "enableCustomReturn" method on the
* FileUploadStatus object so that the default fileupload response will not be sent.
*
- * @param htUpload The Status Hashtable that contains the items that have been uploaded for post-processing use
+ * @param writer The writer to write the output
+ * @param status The Status object that contains the items that have been uploaded for post-processing use
*/
public static void writeUploadResponse(PrintWriter writer, FileUploadStatus status) {
Hashtable<String, String> htUpload = status.getUploadItems();
@@ -510,10 +516,10 @@
* so the output could be monitored
*
* @param item The Commons Fileupload item being loaded
- * @param file File path to write uploaded data.
+ * @param fileName File name to write uploaded data.
* @throws Exception Exceptions propagated from Apache Commons Fileupload classes
*/
- public void write(FileItemStream item, String filePath) throws Exception {
+ public void write(FileItemStream item, String fileName) throws Exception {
// use name for update of session
String itemName = item.getName();
@@ -523,7 +529,7 @@
logger.fine("Getting fileItem from memory - " + itemName);
- OutputStream fout = fs.create(filePath);
+ OutputStream fout = fs.create(fileName);
// It would have been more efficient to use NIO if we are writing to
// the local filesystem. However, since we need to support DFS,
@@ -531,7 +537,7 @@
// TO DO: Optimize write if required.
try {
- byte[] buf = new byte[2048];
+ byte[] buf = new byte[8192];
int count, size = 0;
InputStream is = item.openStream();
while ((count = is.read(buf)) != -1) {
@@ -549,14 +555,55 @@
/**
*
* @param item FileItemStream from the file upload handler
- * @param imagePath path to the save the image.
- * @param thumbnailPath path prefix to the thumbnail. Extension is appended.
+ * @param imageName name to save the image.
+ * @param thumbnailName name to save the thumbnail. Extension is appended.
* @throws java.lang.Exception
*/
public void writeWithThumbnail(FileItemStream item,
- String imagePath, String thumbnailPath) throws Exception {
- WebappUtil.saveImageWithThumbnail(item.openStream(), imagePath, thumbnailPath);
+ String imageName, String thumbnailName) throws Exception {
+ // use name for update of session
+ String itemName = item.getName();
+
+ ServiceLocator locator = ServiceLocator.getInstance();
+
+ FileSystem fs = locator.getFileSystem();
+
+ logger.fine("Getting fileItem from memory - " + itemName);
+
+ OutputStream imgOut = null;
+ OutputStream thumbOut = null;
+ InputStream is = null;
+ try {
+ imgOut = fs.create(imageName);
+ thumbOut = fs.create(thumbnailName);
+ // It would have been more efficient to use NIO if we are writing to
+ // the local filesystem. However, since we need to support DFS,
+ // a simple solution is provided.
+ // TO DO: Optimize write if required.
+
+ is = item.openStream();
+ FileUploadStatus status = getFileUploadStatus();
+ status.setCurrentItem(itemName);
+
+ WebappUtil.saveImageWithThumbnail(is, imgOut, thumbOut, status);
+ } finally {
+ if (imgOut != null)
+ try {
+ imgOut.close();
+ } catch (IOException e) {
- }
+ }
+ if (thumbOut != null)
+ try {
+ thumbOut.close();
+ } catch (IOException e) {
+ }
+ if (is != null)
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ }
+ }
public void updateSessionStatus(String itemName, long incrementAmount) {
FileUploadStatus status = getFileUploadStatus();
Index: ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/ImageScaler.java
===================================================================
--- ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/ImageScaler.java (revision 773143)
+++ ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/ImageScaler.java Fri Oct 16 12:06:38 PDT 2009
@@ -163,7 +163,7 @@
* @param from the path of the original image
* @param to the path of the target thumbnail
*/
- public void resizeWithGraphics(String to) throws IOException {
+ public void resizeWithGraphics(OutputStream to) throws IOException {
BufferedImage th = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = th.createGraphics();
/* Simplify - trade off performance for quality
@@ -183,15 +183,8 @@
// Added for for distributed file system support
// Store image based on local of distributed files systems
- FileSystem fs = ServiceLocator.getInstance().getFileSystem();
- OutputStream oStream = fs.create(to);
- ImageIO.write(th, format, oStream);
-
- try {
- oStream.close();
+ ImageIO.write(th, format, to);
- }
+ }
- catch (Exception e) {}
- }
/* Using Affine transform
* for transform with power(0.5, etc.). fastest.
Index: ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/rest/EventRestAction.java
===================================================================
--- ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/rest/EventRestAction.java (revision 822866)
+++ ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/rest/EventRestAction.java Fri Oct 16 23:04:31 PDT 2009
@@ -18,6 +18,7 @@
package org.apache.olio.webapp.rest;
import org.apache.olio.webapp.controller.Action;
+import org.apache.olio.webapp.controller.WebConstants;
import org.apache.olio.webapp.model.Address;
import org.apache.olio.webapp.model.ModelFacade;
import org.apache.olio.webapp.util.WebappUtil;
@@ -83,7 +84,8 @@
// file upload
logger.finer("AddEvent ... ");
FileUploadHandler fuh = new FileUploadHandler();
- Hashtable<String, String> htUpload = fuh.handleFileUpload(request, response);
+ Hashtable<String, String> htUpload = fuh.getInitialParams(request, response);
+
// file is upload check for error and then write to database
if (htUpload != null) {
StringBuilder sb = new StringBuilder();
@@ -98,8 +100,8 @@
return "/site.jsp?page=error.jsp";
}
- if (type != null && type.equals("Update")) {
- event = updateEvent(request, modelFacade, htUpload);
+ if (type.equals("Update")) {
+ event = getEvent(modelFacade, htUpload);
} else {
event = createEvent(request, modelFacade, htUpload);
if (request.getSession(true).getAttribute("userBean") != null) {
@@ -108,7 +110,14 @@
logger.log(Level.FINER, "A new Event has been added and persisted");
}
}
+
+ String id = String.valueOf(event.getSocialEventID());
+ htUpload = fuh.handleFileUpload(id, request, response);
+
+ // Update the event with the right stuff.
+ updateEvent(event, request, modelFacade, htUpload);
+
- // clear the cache
+ // clear the cache
WebappUtil.clearCache("/event/list");
response.sendRedirect(request.getContextPath() + "/event/detail?socialEventID=" + event.getSocialEventID());
return null;
@@ -176,7 +185,7 @@
modelFacade.updateSocialEvent(event);
}
- String s = this.getAttendeesAsJson(event.getAttendees(), status);
+ String s = getAttendeesAsJson(event.getAttendees(), status);
logger.finer("\n*** people = " + s);
response.setContentType("application/json;charset=UTF-8");
@@ -265,6 +274,7 @@
}
public SocialEvent createEvent(HttpServletRequest request, ModelFacade modelFacade, Hashtable<String, String> htUpload) {
+ /* We don't worry about the address at creation time. Only do at update.
String street1 = htUpload.get(STREET1_PARAM);
String street2 = htUpload.get(STREET2_PARAM);
String city = htUpload.get(CITY_PARAM);
@@ -272,6 +282,7 @@
String country = htUpload.get(COUNTRY_PARAM);
String zip = htUpload.get(ZIP_PARAM);
Address address = WebappUtil.handleAddress(context, street1, street2, city, state, zip, country);
+ */
String title = htUpload.get(TITLE_PARAM);
String description = htUpload.get(DESCRIPTION_PARAM);
@@ -339,7 +350,7 @@
logger.finer("\n***local = " + localCal + "\n Millis = " + localCal.getTimeInMillis());
Timestamp eventTimestamp = new Timestamp(localCal.getTimeInMillis());
- SocialEvent socialEvent = new SocialEvent(title, summary, description, submitterUserName, address, telephone, 0, 0,
+ SocialEvent socialEvent = new SocialEvent(title, summary, description, submitterUserName, null, telephone, 0, 0,
imagex, thumbImage, literaturex, eventTimestamp);
logger.finer("Event title = " + socialEvent.getTitle());
@@ -352,21 +363,23 @@
return socialEvent;
}
- public SocialEvent updateEvent(HttpServletRequest request, ModelFacade modelFacade, Hashtable<String, String> htUpload) throws IOException {
- // Update requires an id
+ public SocialEvent getEvent(ModelFacade modelFacade, Hashtable<String, String> htUpload) {
String sids = htUpload.get("socialEventID");
if (sids == null) {
throw new RuntimeException("socialEventID is not set for updateEVent");
}
- SocialEvent event = null;
try {
int id = Integer.parseInt(sids);
- event = modelFacade.getSocialEvent(id);
+ return modelFacade.getSocialEvent(id);
} catch (Exception e) {
throw new RuntimeException("updateSocialEvent: SocialEvent could not be retrieved - id = " +
sids);
}
+ }
+ public SocialEvent updateEvent(SocialEvent event, HttpServletRequest request, ModelFacade modelFacade, Hashtable<String, String> htUpload) throws IOException {
+
+ // Update requires an id
String street1 = htUpload.get(STREET1_PARAM);
String street2 = htUpload.get(STREET2_PARAM);
String city = htUpload.get(CITY_PARAM);
Index: ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/fs/local/LocalFileSystem.java
===================================================================
--- ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/fs/local/LocalFileSystem.java (revision 773143)
+++ ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/fs/local/LocalFileSystem.java Thu Oct 15 17:14:03 PDT 2009
@@ -19,12 +19,15 @@
package org.apache.olio.webapp.util.fs.local;
import org.apache.olio.webapp.util.fs.FileSystem;
+import org.apache.olio.webapp.filestore.LocalFS;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.logging.Logger;
/**
*
@@ -33,46 +36,181 @@
public class LocalFileSystem implements FileSystem {
public static String FS_KEY = "localFS";
+ private static Logger logger = Logger.getLogger(LocalFS.class.getName());
+ private String baseLocation;
+
+ // Indices into the attributes array.
+ private static final int ID = 0;
+ private static final int TYPE = 1;
+
/** Creates a new instance of LocalFileSystem */
public LocalFileSystem() {
+ baseLocation = System.getProperty("olio.localfs.basedir", "/filestore");
}
- public OutputStream create(String path) throws IOException {
- return create (path, 0, true);
+ private String getType(char t) {
+ String type = null;
+ switch (t) {
+ case 'P' :
+ case 'p' : type = "person"; break;
+ case 'E' :
+ case 'e' : type = "event"; break;
- }
+ }
+ return type;
+ }
- public OutputStream create(String path, int replication) throws IOException {
- return create (path, replication, true);
+ private String[] mapAttributes(String fileName) {
+ // Do pattern matching and splitting.
+ char prefix = fileName.charAt(0);
+ String[] attrs = new String[2];
+ attrs[TYPE] = getType(prefix);
+ int dotIdx = fileName.lastIndexOf('.');
+ char postfix = fileName.charAt(dotIdx - 1);
+ if (Character.isDigit(postfix)) {
+ attrs[ID] = fileName.substring(1, dotIdx);
+ attrs[TYPE] += 's';
+ } else if (postfix == 't' || postfix == 'T') {
+ attrs[ID] = fileName.substring(1, dotIdx - 1);
+ attrs[TYPE] += "Thumbs";
+ } else if (postfix == 'l' || postfix == 'L') {
+ attrs[ID] = fileName.substring(1, dotIdx - 2);
+ attrs[TYPE] += "Lits";
+ } else {
+ logger.warning("Invalid file name pattern " + fileName);
+ attrs[TYPE] = null;
- }
+ }
+ return attrs;
+ }
- public OutputStream create(String path, int replication, boolean overwrite) throws IOException {
- // The replication factor is ignored for LocalFileSystem
- if (!overwrite) {
- File file = new File(path);
- if (file.exists())
- throw new IOException ("File exists - " + path);
+ private String getFullPath(String fileName, String[] attrs) {
+ if (attrs == null) {
+ attrs = mapAttributes(fileName);
}
-
+
- return new FileOutputStream (path);
+ //build path
+ long id = Long.parseLong(attrs[ID]);
+ String dirPrimaryPath = String.format("%03d", id % 1000l);
+ String dirSecondaryPath = String.format("%03d", id / 1000000l % 1000l);
+
+
+ if(!"invalid".equals(attrs[TYPE])) {
+ StringBuilder path = new StringBuilder();
+ path.append(baseLocation).append('/').append(attrs[TYPE]);
+ path.append('/').append(dirPrimaryPath).append('/');
+ path.append(dirSecondaryPath).append('/').append(fileName);
+ return path.toString();
+ } else {
+ //return invalid as a failed message
+ return null;
- }
+ }
+ }
- public boolean exists(String path) {
- File file = new File(path);
- return file.exists();
+ /**
+ * Creates a file.
+ *
+ * @param name The file name
+ * @return An output stream to write the content of the file
+ * @throws java.io.IOException Error creating the file
+ */
+ public OutputStream create(String name) throws IOException {
+ return create (name, 0, true);
}
- public InputStream open(String path) throws IOException {
- /* Will not check for the existence of the file. */
+ /**
+ * Creates a file.
+ *
+ * @param name The file name
+ * @param replication The number of copies of the file to keep around
+ * @return An output stream to write the content of the file
+ * @throws java.io.IOException Error creating the file
+ */ public OutputStream create(String name, int replication) throws IOException {
+ return create (name, replication, true);
+ }
-
+
- return new FileInputStream (path);
+ /**
+ * Creates a file.
+ *
+ * @param name The file name
+ * @param replication The number of copies of the file to keep around
+ * @param overwrite Overwrite the file if already exists?
+ * @return An output stream to write the content of the file
+ * @throws java.io.IOException Error creating the file
+ */
+ public OutputStream create(String name, int replication, boolean overwrite) throws IOException {
+ File fileToCreate = new File(name);
+ String fileName = fileToCreate.getName();
+ String[] attrs = mapAttributes(fileName);
+ String destPath = getFullPath(name, attrs);
+
+ if (destPath != null) {
+ File dest = new File(destPath);
+ if (overwrite || !dest.exists()) {
+ File destDir = dest.getParentFile();
+ if (!destDir.isDirectory())
+ if (!destDir.mkdirs()) {
+ logger.warning("Cannot create directory " +
+ destDir.toString());
+ return null;
- }
+ }
- public void delete(String path) throws IOException {
- File file = new File(path);
- if (file.exists())
- file.delete();
+ FileOutputStream out = new FileOutputStream(dest);
+ return out;
- }
+ }
+ }
+ return null;
+ }
+ /**
+ * Checks whether a file with the name already exists.
+ *
+ * @param name The name of the file to check
+ * @return Whether the file in question does indeed exist
+ */
+ public boolean exists(String name) {
+ String fullPath = getFullPath(name, null);
+ if (fullPath != null) {
+ File f = new File(fullPath);
+ return f.isFile();
+ }
+ return false;
+ }
+
+ /**
+ * Opens the file for reading. Note, we cannot change an existing file
+ * with this file architecture. To change, you need to create a new file.
+ *
+ * @param name The file name
+ * @return An input stream allowing reading the content of the file
+ * @throws java.io.IOException Error opening the file
+ */
+ public InputStream open(String name) throws IOException {
+ String fullPath = getFullPath(name, null);
+ if (fullPath != null) {
+ File f = new File(fullPath);
+ if (f.isFile())
+ return new FileInputStream(f);
+ }
+ return null;
+ }
+
+ /**
+ * Deletes a file.
+ *
+ * @param name The name of the file to delete
+ * @throws java.io.IOException Error deleting the file
+ */
+ public void delete(String name) throws IOException {
+ String fullPath = getFullPath(name, null);
+ if (fullPath != null) {
+ File f = new File(fullPath);
+ f.delete();
+ }
+ }
+
+ /**
+ * Checks whether this file system is local.
+ * @return Always true for the LocalFileSystem
+ */
public boolean isLocal() {
return true;
}
Index: ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WebappUtil.java
===================================================================
--- ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WebappUtil.java (revision 822866)
+++ ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WebappUtil.java Fri Oct 16 13:15:57 PDT 2009
@@ -22,6 +22,8 @@
import org.apache.olio.webapp.model.Address;
import org.apache.olio.webapp.model.SocialEvent;
import org.apache.olio.webapp.model.SocialEventTag;
+import org.apache.olio.webapp.fileupload.FileUploadStatus;
+
import java.text.MessageFormat;
import java.util.PropertyResourceBundle;
import java.util.logging.Level;
@@ -147,24 +149,25 @@
/* Load Image, create thumbnail and save images.
This does not close the Input Stream */
- public static boolean saveImageWithThumbnail (InputStream is, String imagePath,
- String thumbnailPath) throws IOException {
+ public static boolean saveImageWithThumbnail (InputStream is,
+ OutputStream imageOut,
+ OutputStream thumbnailOut,
+ FileUploadStatus status)
+ throws IOException {
ImageScaler scaler = new ImageScaler ();
- FileOutputStream fos = new FileOutputStream (imagePath);
- WriteThroughInputStream wis = new WriteThroughInputStream (is, fos);
- // logger.finer(" the imagePath in saveImageWithThumbnail is "+ imagePath);
+ WriteThroughInputStream wis =
+ new WriteThroughInputStream(is, imageOut, status);
try {
scaler.customLoad(wis);
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
//ex.printStackTrace();
}
- if (thumbnailPath != null) {
- scaler.resizeWithGraphics(thumbnailPath);
+ if (thumbnailOut != null) {
+ scaler.resizeWithGraphics(thumbnailOut);
}
// logger.finer(" the thumbNailPath in saveImageWithThumbnail is "+ thumbnailPath);
- wis.closeOutputStream();
return true;
}
@@ -175,14 +178,25 @@
if (idx > 0) {
thumbPath = path.substring(0, idx)+"_thumb"+path.substring(idx, path.length());
}
-
+
+ FileOutputStream thumbOut = null;
try {
ImageScaler imgScaler = new ImageScaler(path);
+ thumbOut = new FileOutputStream(thumbPath);
imgScaler.keepAspectWithWidth();
- imgScaler.resizeWithGraphics(thumbPath);
+
+ imgScaler.resizeWithGraphics(thumbOut);
} catch (Exception e) {
logger.log(Level.SEVERE, "ERROR in generating thumbnail", e);
+ } finally {
+ if (thumbOut != null) {
+ try {
+ thumbOut.close();
+ } catch (IOException e) {
- }
+ }
+ }
+
+ }
// remove path info and just return the thumb file name
thumbPath=thumbPath.substring(thumbPath.lastIndexOf("/") + 1);
@@ -218,7 +232,7 @@
/**
* This method uses the default message strings property file to resolve
* resultant string to show to an end user
- * @param Key to use in MessageString.properties file
+ * @param key to use in MessageString.properties file
*
* @return Formated message for external display
*/
Index: ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/rest/PersonRestAction.java
===================================================================
--- ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/rest/PersonRestAction.java (revision 822866)
+++ ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/rest/PersonRestAction.java Mon Oct 19 15:26:47 PDT 2009
@@ -75,14 +75,17 @@
if (path.equals("/person/fileuploadPerson")) {
// file upload
FileUploadHandler fuh = new FileUploadHandler();
- Hashtable<String, String> htUpload = fuh.handleFileUpload(request, response);
+ Hashtable<String, String> htUpload = fuh.getInitialParams(request, response);
+
// file is upload check for error and then write to database
if (htUpload != null) {
+ /*
StringBuilder sb = new StringBuilder();
for (String key : htUpload.keySet()) {
sb.append(key);
sb.append(",");
}
+ */
//logger.finer("\n***elements = " + sb.toString());
//createUser(request, htUpload);
@@ -92,7 +95,7 @@
boolean isEditable = Boolean.parseBoolean(request.getParameter("isEditable"));
if (isEditable) {
- newEditPerson = updateUser(request, htUpload, fuh);
+ newEditPerson = getPerson(request);
} else {
newEditPerson = createUser(request, htUpload, fuh);
}
@@ -100,6 +103,10 @@
logger.log(Level.FINER, "A new Person has been added and persisted");
request.setAttribute("displayPerson", newEditPerson);
+ String id = String.valueOf(newEditPerson.getUserID());
+ htUpload = fuh.handleFileUpload(id, request, response);
+
+ updateUser(newEditPerson, htUpload);
}
return "/site.jsp?page=personContent.jsp";
@@ -246,17 +253,20 @@
String firstName = htUpload.get(FIRST_NAME_PARAM);
String lastName = htUpload.get(LAST_NAME_PARAM);
String summary = htUpload.get(SUMMARY_PARAM);
+ /* We do the address in the update phase.
String street1 = htUpload.get(STREET1_PARAM);
String street2 = htUpload.get(STREET2_PARAM);
String city = htUpload.get(CITY_PARAM);
String state = htUpload.get(STATE_PARAM);
String country = htUpload.get(COUNTRY_PARAM);
String zip = htUpload.get(ZIP_PARAM);
+ */
String timezone = htUpload.get(TIMEZONE_PARAM);
String telephone = htUpload.get(TELEPHONE_PARAM);
String email = htUpload.get(EMAIL_PARAM);
- Address address = WebappUtil.handleAddress(context, street1, street2, city, state, zip, country);
+ // Address address = WebappUtil.handleAddress(context, street1, street2, city, state, zip, country);
+
// get image from fileupload
String imageURL = htUpload.get(UPLOAD_PERSON_IMAGE_PARAM);
String thumbImage;
@@ -271,7 +281,7 @@
" last_name" + lastName +
" summary" + summary);
- Person person = new Person(userName, password, firstName, lastName, summary, email, telephone, imageURL, thumbImage, timezone, address);
+ Person person = new Person(userName, password, firstName, lastName, summary, email, telephone, imageURL, thumbImage, timezone, null);
ModelFacade mf = (ModelFacade) context.getAttribute(MF_KEY);
//do not really need username since you set this value, not sure why it is returned
//String userName = mf.addPerson(person, userSignOn);
@@ -287,7 +297,7 @@
return person;
}
- private Person updateUser(HttpServletRequest request, Hashtable<String, String> htUpload, FileUploadHandler fuh) {
+ private Person updateUser(Person person, Hashtable<String, String> htUpload) {
String userName = htUpload.get(USER_NAME_PARAM);
String password = htUpload.get(PASSWORD_PARAM);
String firstName = htUpload.get(FIRST_NAME_PARAM);
@@ -329,7 +339,7 @@
" last_name" + lastName +
" summary" + summary);
- Person person = new Person(userName, password, firstName, lastName, summary, email, telephone, imageURL, thumbImage, timezone, address);
+ //Person person = new Person(userName, password, firstName, lastName, summary, email, telephone, imageURL, thumbImage, timezone, address);
//ModelFacade mf= (ModelFacade) context.getAttribute(MF_KEY);
//do not really need username since you set this value, not sure why it is returned
//String userName = mf.addPerson(person, userSignOn);
Index: ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/model/Person.java
===================================================================
--- ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/model/Person.java (revision 773143)
+++ ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/model/Person.java Mon Oct 19 14:24:56 PDT 2009
@@ -58,7 +58,8 @@
@Entity
@Table (name="PERSON")
public class Person implements java.io.Serializable {
-
+
+ private int userID;
private String userName;
private String password;
private String firstName;
@@ -102,7 +103,18 @@
this.address = address;
}
+ @TableGenerator(name="PERSON_ID_GEN",
+ table="ID_GEN",
+ pkColumnName="GEN_KEY",
+ valueColumnName="GEN_VALUE",
+ pkColumnValue="PERSON_ID",
+ allocationSize=50000)
+ @GeneratedValue(strategy=GenerationType.TABLE,generator="PERSON_ID_GEN")
@Id
+ public int getUserID() {
+ return userID;
+ }
+
public String getUserName() {
return userName;
}
@@ -197,6 +209,10 @@
return outgoingInvitations;
}
+ public void setUserID(int socialEventID) {
+ this.UserID = UserID;
+ }
+
public void setOutgoingInvitations(Collection<Invitation> outgoingInvitations) {
this.outgoingInvitations = outgoingInvitations;
}
Index: ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WriteThroughInputStream.java
===================================================================
--- ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WriteThroughInputStream.java (revision 773143)
+++ ../../projects/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WriteThroughInputStream.java Fri Oct 16 13:15:57 PDT 2009
@@ -18,6 +18,8 @@
package org.apache.olio.webapp.util;
+import org.apache.olio.webapp.fileupload.FileUploadStatus;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -32,13 +34,20 @@
private OutputStream os;
private InputStream is;
+ private FileUploadStatus status;
-
+
public WriteThroughInputStream (InputStream is, OutputStream os) {
this.is = is;
this.os = os;
}
-
+
- @Override
+ public WriteThroughInputStream (InputStream is, OutputStream os,
+ FileUploadStatus status) {
+ this.is = is;
+ this.os = os;
+ this.status = status;
+ }
+
public int read() throws IOException {
byte[] b = new byte[1];
return read (b);
@@ -49,6 +58,8 @@
int rCount = is.read(buf, offset, length);
if (os != null && rCount != -1)
os.write(buf, offset, rCount);
+ if (status != null)
+ status.incrementCurrentSizeWritten(rCount);
return rCount;
}