001: /* SmartAuWriter.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Tue Dec 4 09:58:48 2007, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zkmax.au.http;
020:
021: import java.io.IOException;
022:
023: import javax.servlet.http.HttpServletRequest;
024: import javax.servlet.http.HttpServletResponse;
025:
026: import org.zkoss.util.ScalableTimer;
027: import org.zkoss.util.ScalableTimerTask;
028:
029: import org.zkoss.zk.au.AuWriter;
030: import org.zkoss.zk.au.http.HttpAuWriter;
031:
032: /**
033: * A smart AU writer that will generate some output to client first if
034: * the processing takes more than the time specified in the timeout argument
035: * of {@link #open}.
036: *
037: * @author tomyeh
038: * @since 3.0.1
039: */
040: public class SmartAuWriter extends HttpAuWriter {
041: /** The first few bytes of the output header (byte[]). */
042: private static final byte[] OUTPUT_HEAD_BYTES = OUTPUT_HEAD
043: .getBytes();
044: private static final ScalableTimer _timer = new ScalableTimer(20,
045: 25);
046:
047: private Task _tmoutTask;
048: /** The output stream. It is not null only if _tmoutTask is not null. */
049: private HttpServletResponse _res;
050: /** true if timeout happens. */
051: private boolean _timeout;
052:
053: public SmartAuWriter() {
054: }
055:
056: /** Opens the connection.
057: * It starts a timer and generate some output to client first if
058: * the processing take more than the time specified in the timeout argument.
059: */
060: public AuWriter open(Object request, Object response, int timeout)
061: throws IOException {
062: if (timeout > 0) {
063: _res = (HttpServletResponse) response;
064: _timer.schedule(_tmoutTask = new Task(), timeout);
065: }
066: return super .open(request, response, timeout);
067: }
068:
069: protected void flush(HttpServletRequest request,
070: HttpServletResponse response) throws IOException {
071: final boolean timeout;
072: final Task task = _tmoutTask;
073: if (task != null)
074: task.cancel();
075:
076: synchronized (this ) {
077: _tmoutTask = null;
078: _res = null;
079: timeout = _timeout;
080: _timeout = false;
081: }
082:
083: if (timeout) {
084: response.getOutputStream().write(
085: _out.getBuffer().substring(OUTPUT_HEAD.length())
086: .getBytes("UTF-8"));
087: response.flushBuffer();
088: } else {
089: super .flush(request, response);
090: }
091: }
092:
093: private class Task extends ScalableTimerTask {
094: public void exec() {
095: synchronized (this ) {
096: if (_tmoutTask != null) {
097: //we have to write something to client to let the Ajax request
098: //advance XMLHttpRequest.readyState (to 3).
099: //Otherwise, the client may consider it as timeout and resend
100: try {
101: _res.setContentType(CONTENT_TYPE);
102: _res.getOutputStream().write(OUTPUT_HEAD_BYTES);
103: _res.flushBuffer();
104: } catch (IOException ex) { //ignore it
105: }
106: _tmoutTask = null; //mark as done
107: _res = null; //clean up
108: _timeout = true; //let flush know OUTPUT_HEAD is sent
109: }
110: }
111: }
112: }
113: }
|