001: /*
002: * $Id: MultipartCallingConvention.java,v 1.8 2007/09/18 11:27:13 agoubard Exp $
003: */
004: package com.mycompany.fileupload.multipart;
005:
006: import java.io.ByteArrayOutputStream;
007: import java.io.InputStream;
008: import java.io.IOException;
009: import java.io.PrintWriter;
010: import java.io.StringReader;
011: import java.util.ArrayList;
012: import java.util.Enumeration;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import javax.servlet.http.HttpServletRequest;
017: import javax.servlet.http.HttpServletResponse;
018:
019: import org.apache.commons.fileupload.FileItem;
020: import org.apache.commons.fileupload.FileItemFactory;
021: import org.apache.commons.fileupload.FileUpload;
022: import org.apache.commons.fileupload.FileUploadException;
023: import org.apache.commons.fileupload.disk.DiskFileItemFactory;
024: import org.apache.commons.fileupload.servlet.ServletFileUpload;
025:
026: import org.xins.common.Utils;
027: import org.xins.common.collections.BasicPropertyReader;
028: import org.xins.common.text.ParseException;
029: import org.xins.common.text.TextUtils;
030: import org.xins.common.types.standard.Hex;
031: import org.xins.common.xml.Element;
032: import org.xins.common.xml.ElementParser;
033:
034: import org.xins.server.CallResultOutputter;
035: import org.xins.server.CustomCallingConvention;
036: import org.xins.server.FunctionNotSpecifiedException;
037: import org.xins.server.FunctionRequest;
038: import org.xins.server.FunctionResult;
039: import org.xins.server.InvalidRequestException;
040:
041: /**
042: * Calling convention that supports RFC 1867 multipart content. This content
043: * type supports uploading of content items (typically: files.)
044: *
045: * <p>For an example of the HTML form, look at the upload.html file located in
046: * the demo\xins-project\apis\fileupload directory.
047: *
048: * <p>For each defined input of type file, you must define two input parameters:
049: * <input field name>Name of type _text for the name of the file and
050: * <input field name>Content of type _hex for the content of the file.
051: *
052: * <p>Uploaded items will be retained in memory as long as they are reasonably
053: * small. Larger items will be written to a temporary file on disk. Very large
054: * upload requests are not permitted.
055: *
056: * @version $Revision: 1.8 $ $Date: 2007/09/18 11:27:13 $
057: * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
058: * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
059: */
060: public class MultipartCallingConvention extends CustomCallingConvention {
061:
062: /**
063: * Constructs a new <code>MultipartCallingConvention</code>.
064: */
065: public MultipartCallingConvention() {
066: // empty
067: }
068:
069: protected boolean matches(HttpServletRequest httpRequest)
070: throws Exception {
071:
072: // Requirement 1: The request must be multi-part
073: if (!httpRequest.getContentType().startsWith(
074: FileUpload.MULTIPART_FORM_DATA)) {
075: return false;
076: } else {
077: return true;
078: }
079: }
080:
081: protected FunctionRequest convertRequestImpl(
082: HttpServletRequest httpRequest)
083: throws InvalidRequestException,
084: FunctionNotSpecifiedException {
085:
086: // The request must be multi-part
087: if (!httpRequest.getContentType().startsWith(
088: FileUpload.MULTIPART_FORM_DATA)) {
089: throw new InvalidRequestException(
090: "Request is not multi-part.");
091: }
092:
093: // Create a factory for disk-based file items
094: FileItemFactory factory = new DiskFileItemFactory();
095:
096: // Create a new file upload handler
097: ServletFileUpload upload = new ServletFileUpload(factory);
098:
099: // Parse the request (list contains FileItem instances)
100: List itemList;
101: try {
102: itemList = upload.parseRequest(httpRequest);
103: } catch (FileUploadException exception) {
104: throw new InvalidRequestException(
105: "Failed to parse request.", exception);
106: }
107:
108: // Convert the list to a PropertyReader instance
109: BasicPropertyReader params = new BasicPropertyReader();
110: for (int i = 0; i < itemList.size(); i++) {
111: FileItem item = (FileItem) itemList.get(i);
112: String name = item.getFieldName();
113: if (item.isFormField()) {
114: String value = item.getString();
115: params.set(name, value);
116: } else {
117: String fileName = item.getName();
118: params.set(name + "Name", fileName);
119: try {
120: InputStream inputContent = item.getInputStream();
121: ByteArrayOutputStream baos = new ByteArrayOutputStream();
122: int availableBytes = inputContent.available();
123: while (availableBytes > 0) {
124: byte[] buffer = new byte[availableBytes];
125: inputContent.read(buffer);
126: baos.write(buffer);
127: availableBytes = inputContent.available();
128: }
129: byte[] fileContent = baos.toByteArray();
130: inputContent.close();
131: baos.close();
132: params.set(name + "Content", Hex
133: .toString(fileContent));
134: } catch (IOException ioe) {
135: throw new InvalidRequestException(
136: "Failed to read the input file.", ioe);
137: }
138: }
139: }
140:
141: // Determine the function name
142: String function = params.get("_function");
143: if (function == null) {
144: throw new FunctionNotSpecifiedException();
145: }
146:
147: // Get data section
148: String dataSectionValue = params.get("_data");
149: Element dataElement = null;
150: if (dataSectionValue != null && dataSectionValue.length() > 0) {
151: ElementParser parser = new ElementParser();
152:
153: // Parse the data section
154: StringReader reader = new StringReader(dataSectionValue);
155: try {
156: dataElement = parser.parse(reader);
157:
158: // I/O error, should never happen on a StringReader
159: } catch (IOException exception) {
160: throw Utils.logProgrammingError(exception);
161:
162: // Parsing error
163: } catch (ParseException exception) {
164: String detail = "Cannot parse the data section.";
165: throw new InvalidRequestException(detail, exception);
166: }
167: }
168:
169: // Construct and return the request object
170: return new FunctionRequest(function, params, dataElement);
171: }
172:
173: protected void convertResultImpl(FunctionResult xinsResult,
174: HttpServletResponse httpResponse,
175: HttpServletRequest httpRequest) throws IOException {
176:
177: // Send the XML output to the stream and flush
178: httpResponse.setContentType("text/xml; charset=UTF-8");
179: PrintWriter out = httpResponse.getWriter();
180: httpResponse.setStatus(HttpServletResponse.SC_OK);
181: CallResultOutputter.output(out, xinsResult);
182: out.close();
183: }
184: }
|