001: package com.icesoft.faces.webapp.http.core;
002:
003: import com.icesoft.faces.application.D2DViewHandler;
004: import com.icesoft.faces.component.FileUploadComponent;
005: import com.icesoft.faces.context.BridgeFacesContext;
006: import com.icesoft.faces.context.View;
007: import com.icesoft.faces.webapp.http.common.Configuration;
008: import com.icesoft.faces.webapp.http.common.Request;
009: import com.icesoft.faces.webapp.http.common.Server;
010: import com.icesoft.faces.webapp.http.common.standard.StreamingContentHandler;
011: import org.apache.commons.fileupload.FileItemIterator;
012: import org.apache.commons.fileupload.FileItemStream;
013: import org.apache.commons.fileupload.ProgressListener;
014: import org.apache.commons.fileupload.servlet.ServletFileUpload;
015: import org.apache.commons.fileupload.util.Streams;
016: import org.apache.commons.logging.Log;
017: import org.apache.commons.logging.LogFactory;
018:
019: import javax.servlet.http.HttpServletRequest;
020: import java.io.IOException;
021: import java.io.Writer;
022: import java.util.Map;
023:
024: public class UploadServer implements Server {
025: private static final Log Log = LogFactory
026: .getLog(UploadServer.class);
027: private Map views;
028: private long maxSize;
029: private String uploadDirectory;
030: private boolean uploadDirectoryAbsolute;
031:
032: public UploadServer(Map views, Configuration configuration) {
033: this .views = views;
034: this .maxSize = configuration.getAttributeAsLong(
035: "uploadMaxFileSize", 3 * 1024 * 1024);//3Mb
036: //Partial fix for http://jira.icefaces.org/browse/ICE-1600
037: this .uploadDirectory = configuration.getAttribute(
038: "uploadDirectory", "");
039: this .uploadDirectoryAbsolute = configuration
040: .getAttributeAsBoolean("uploadDirectoryAbsolute", false);
041: }
042:
043: public void service(final Request request) throws Exception {
044: final ServletFileUpload uploader = new ServletFileUpload();
045: final ProgressCalculator progressCalculator = new ProgressCalculator();
046: uploader.setFileSizeMax(maxSize);
047: uploader.setProgressListener(new ProgressListener() {
048: public void update(long read, long total, int chunkIndex) {
049: progressCalculator.progress(read, total);
050: }
051: });
052: request.detectEnvironment(new Request.Environment() {
053: public void servlet(Object req, Object resp)
054: throws Exception {
055: final HttpServletRequest servletRequest = (HttpServletRequest) req;
056: FileItemIterator iter = uploader
057: .getItemIterator(servletRequest);
058: String viewIdentifier = null;
059: String componentID = null;
060: while (iter.hasNext()) {
061: FileItemStream item = iter.next();
062: if (item.isFormField()) {
063: String name = item.getFieldName();
064: if ("ice.component".equals(name)) {
065: componentID = Streams.asString(item
066: .openStream());
067: } else if ("ice.view.active".equals(name)) {
068: viewIdentifier = Streams.asString(item
069: .openStream());
070: }
071: } else {
072: final View view = (View) views
073: .get(viewIdentifier);
074: final BridgeFacesContext context = view
075: .getFacesContext();
076: final FileUploadComponent component = (FileUploadComponent) D2DViewHandler
077: .findComponent(componentID, context
078: .getViewRoot());
079: progressCalculator.setListenerAndContext(
080: component, context);
081: try {
082: view.makeCurrent();
083: component.upload(item, uploadDirectory,
084: uploadDirectoryAbsolute, maxSize,
085: context, servletRequest
086: .getSession()
087: .getServletContext(),
088: servletRequest
089: .getRequestedSessionId());
090: } catch (IOException e) {
091: try {
092: progressCalculator.reset();
093: } catch (Throwable tr) {
094: //ignore
095: }
096: } catch (Throwable t) {
097: try {
098: progressCalculator.reset();
099: } catch (Throwable tr) {
100: //ignore
101: }
102: Log.warn("File upload failed", t);
103: } finally {
104: request
105: .respondWith(new StreamingContentHandler(
106: "text/html", "UTF-8") {
107: public void writeTo(
108: Writer writer)
109: throws IOException {
110: component.renderIFrame(
111: writer, context);
112: }
113: });
114: }
115: }
116: }
117: }
118:
119: public void portlet(Object request, Object response,
120: Object config) {
121: throw new IllegalAccessError(
122: "Cannot upload using a portlet request/response.");
123: }
124: });
125: }
126:
127: public void shutdown() {
128: }
129:
130: private static class ProgressCalculator {
131: private final int GRANULARITY = 10;
132: private FileUploadComponent listener;
133: private BridgeFacesContext context;
134: private int lastGranularlyNotifiablePercent = -1;
135:
136: public void progress(long read, long total) {
137: if (total > 0) {
138: int percentage = (int) ((read * 100L) / total);
139: int percentageAboveGranularity = percentage
140: % GRANULARITY;
141: int granularNotifiablePercentage = percentage
142: - percentageAboveGranularity;
143: boolean shouldNotify = granularNotifiablePercentage > lastGranularlyNotifiablePercent;
144: lastGranularlyNotifiablePercent = granularNotifiablePercentage;
145: if (shouldNotify)
146: potentiallyNotify();
147: }
148: }
149:
150: public void setListenerAndContext(FileUploadComponent listener,
151: BridgeFacesContext context) {
152: this .listener = listener;
153: this .context = context;
154: potentiallyNotify();
155: }
156:
157: public void reset() {
158: BridgeFacesContext ctx = context;
159: FileUploadComponent component = listener;
160: context = null;
161: listener = null;
162: if (ctx != null && component != null) {
163: ctx.setCurrentInstance();
164: component.setProgress(0);
165: }
166: }
167:
168: protected void potentiallyNotify() {
169: if (listener != null
170: && lastGranularlyNotifiablePercent >= 0) {
171: context.setCurrentInstance();
172: listener.setProgress(lastGranularlyNotifiablePercent);
173: }
174: }
175: }
176: }
|