/*
* Copyright 2010 Manuel Carrasco Moñino. (manolo at apache/org)
* http://code.google.com/p/gwtupload
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package gwtupload.server;
import static gwtupload.shared.UConsts.TAG_CANCELED;
import static gwtupload.shared.UConsts.TAG_ERROR;
import gwtupload.server.exceptions.UploadActionException;
import gwtupload.server.exceptions.UploadCanceledException;
import gwtupload.shared.UConsts;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
/**
* <p>Class used to manipulate the data received in the server side.</p>
*
* The user has to implement the method executeAction which receives the list of the FileItems
* sent to the server. Each FileItem represents a file or a form field.
*
* <p>Note: Temporary files are not deleted until the user calls removeSessionFiles(request).</p>
*
* @author Manolo Carrasco Moñino
*
*/
public class UploadAction extends UploadServlet {
private static final long serialVersionUID = -6790246163691420791L;
private boolean removeSessionFiles = false;
private boolean removeData = false;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
ServletContext ctx = config.getServletContext();
removeSessionFiles = Boolean.valueOf(ctx.getInitParameter("removeSessionFiles"));
removeData = Boolean.valueOf(ctx.getInitParameter("removeData"));
logger.info("UPLOAD-ACTION init: removeSessionFiles=" + removeSessionFiles + ", removeData=" + removeData);
}
/**
* Returns the content of a file as an InputStream if it is found in the
* FileItem vector.
*
* @param sessionFiles collection of files sent by the client
* @param parameter field name or file name of the desired file
* @return an ImputString
*/
public static InputStream getFileStream(List<FileItem> sessionFiles, String parameter) throws IOException {
FileItem item = findFileItem(sessionFiles, parameter);
return item == null ? null : item.getInputStream();
}
/**
* Returns the value of a text field present in the FileItem collection.
*
* @param sessionFiles collection of fields sent by the client
* @param fieldName field name
* @return the string value
*/
public static String getFormField(List<FileItem> sessionFiles, String fieldName) {
FileItem item = findItemByFieldName(sessionFiles, fieldName);
return item == null || item.isFormField() == false ? null : item.getString();
}
/**
* This method is called when all data is received in the server.
*
* Temporary files are not deleted until the user calls removeSessionFileItems(request)
*
* Override this method to customize the behavior
*
* @param request
* @param sessionFiles
*
* @return the text/html message to be sent to the client.
* In the case of null the standard response configured for this
* action will be sent.
*
* @throws UploadActionException
* In the case of error
*
*/
public String executeAction(HttpServletRequest request, List<FileItem> sessionFiles) throws UploadActionException {
return null;
}
/**
* This method is called when a received file is requested to be removed and
* is in the collection of items stored in session.
* If the item does't exist in session this method is not called
*
* After it, the item is removed from the session items collection.
*
* Override this method to customize the behavior
*
* @param request
* @param item The item in session
*
* @throws UploadActionException
* In the case of an error, the exception message is returned to
* the client and the item is not deleted from session
*
*/
public void removeItem(HttpServletRequest request, FileItem item) throws UploadActionException {
}
/**
* This method is called when a received file is requested to be removed.
* After it, the item is removed from the session items collection.
*
* Override this method to customize the behavior
*
* @param request
* @param fieldName The name of the filename input
*
* @throws UploadActionException
* In the case of an error, the exception message is returned to
* the client and the item is not deleted from session
*
*/
public void removeItem(HttpServletRequest request, String fieldName) throws UploadActionException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String parameter = request.getParameter(UConsts.PARAM_REMOVE);
if (parameter != null) {
try {
// Notify classes extending this that they have to remove the item.
removeItem(request, parameter);
// Other way to notify classes extending this.
FileItem item = super.findFileItem(getMySessionFileItems(request), parameter);
if (item != null) {
removeItem(request, item);
}
} catch (Exception e) {
renderXmlResponse(request, response, "<" + TAG_ERROR + ">" + e.getMessage() + "</" + TAG_ERROR + ">");
return;
}
// Remove the item saved in session in the case it was not removed yet
super.removeUploadedFile(request, response);
} else {
super.doGet(request, response);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String error = null;
String message = null;
Map<String, String> tags = new HashMap<String, String>();
perThreadRequest.set(request);
try {
// Receive the files and form elements, updating the progress status
error = super.parsePostRequest(request, response);
if (error == null) {
// Fill files status before executing user code which could remove session files
getFileItemsSummary(request, tags);
// Call to the user code
message = executeAction(request, getMyLastReceivedFileItems(request));
}
} catch (UploadCanceledException e) {
renderXmlResponse(request, response, "<" + TAG_CANCELED + ">true</" + TAG_CANCELED + ">");
return;
} catch (UploadActionException e) {
logger.info("ExecuteUploadActionException when receiving a file.", e);
error = e.getMessage();
} catch (Exception e) {
logger.info("Unknown Exception when receiving a file.", e);
error = e.getMessage();
} finally {
perThreadRequest.set(null);
}
String postResponse = null;
AbstractUploadListener listener = getCurrentListener(request);
if (error != null) {
postResponse = "<" + TAG_ERROR + ">" + error + "</" + TAG_ERROR + ">";
renderXmlResponse(request, response, postResponse);
if (listener != null) {
listener.setException(new RuntimeException(error));
}
UploadServlet.removeSessionFileItems(request);
} else {
if (message != null) {
// see issue #139
tags.put("message", "<![CDATA[" + message + "]]>");
}
postResponse = statusToString(tags);
renderXmlResponse(request, response, postResponse, true);
}
finish(request, postResponse);
if (removeSessionFiles) {
removeSessionFileItems(request, removeData);
}
}
}