1 // Copyright (c) 2000 Just Objects B.V. <just@justobjects.nl>
2 // Distributable under LGPL license. See terms of license at gnu.org.
3 
4 package nl.justobjects.pushlet.core;
5 
6 import nl.justobjects.pushlet.util.Log;
7 
8 import javax.servlet.http.HttpServletResponse;
9 import java.io.IOException;
10import java.io.PrintWriter;
11import java.util.Iterator;
12
13/**
14 * Generic implementation of ClientAdapter for browser clients.
15 *
16 * @author Just van den Broecke - Just Objects &copy;
17 * @version $Id: BrowserAdapter.java,v 1.6 2007/11/09 13:15:35 justb Exp $
18 */
19public class BrowserAdapter implements ClientAdapter, Protocol {
20
21    public static final String START_DOCUMENT =
22            "<html><head><meta http-equiv=\"Pragma\" content=\"no-cache\"><meta http-equiv=\"Expires\" content=\"Tue, 31 Dec 1997 23:59:59 GMT\"></head>"
23                    + "<body>"
24                    + "\n<script language=\"JavaScript\"> var url=\" \"; \nfunction refresh() { document.location.href=url; }</script>";
25    public static final String END_DOCUMENT = "</body></html>";
26
27    private PrintWriter servletOut;
28    private HttpServletResponse servletRsp;
29    private int bytesSent;
30
31    /**
32     * Constructor.
33     */
34    public BrowserAdapter(HttpServletResponse aServletResponse) {
35        servletRsp = aServletResponse;
36    }
37
38    /**
39     * Generic init.
40     */
41    public void start() throws IOException {
42        // Keep servlet request/response objects until page ends in stop()
43        // Content type as HTML
44        servletRsp.setStatus(HttpServletResponse.SC_OK);
45        servletRsp.setContentType("text/html;charset=UTF-8");
46
47        // http://www.junlu.com/msg/45902.html
48        // Log.debug("bufsize=" + aRsp.getBufferSize());
49        servletOut = servletRsp.getWriter();
50        send(START_DOCUMENT);
51    }
52
53    /**
54     * Push Event to client.
55     */
56    public void push(Event anEvent) throws IOException {
57        Log.debug("BCA event=" + anEvent.toXML());
58
59        // Check if we should refresh
60        if (anEvent.getEventType().equals(Protocol.E_REFRESH)) {
61            // Append refresh and tail of HTML document
62            // Construct the JS callback line to be sent as last line of doc.
63            // This will refresh the request using the unique id to determine
64            // the subscriber instance on the server. The client will wait for
65            // a number of milliseconds.
66            long refreshWaitMillis = Long.parseLong(anEvent.getField(P_WAIT));
67
68            // Create servlet request for requesting next events (refresh)
69            String url = anEvent.getField(P_URL);
70            String jsRefreshTrigger = "\n<script language=\"JavaScript\">url=\'" + url + "\';\n setTimeout(\"refresh()\", " + refreshWaitMillis + ");\n</script>";
71
72
73            send(jsRefreshTrigger + END_DOCUMENT);
74        } else {
75            send(event2JavaScript(anEvent));
76        }
77    }
78
79    /**
80     * End HTML page in client browser.
81     */
82    public void stop() {
83        // To be garbage collected if adapter remains active
84        servletOut = null;
85    }
86
87    /**
88     * Send any string to browser.
89     */
90    protected void send(String s) throws IOException {
91        // Send string to browser.
92        // Log.debug("Adapter: sending: " + s);
93        if (servletOut == null) {
94            throw new IOException("Client adapter was stopped");
95        }
96
97        servletOut.print(s);
98
99        servletOut.flush();
00
01        // Note: this doesn't seem to have effect
02        // in Tomcat 4/5 if the client already disconnected.
03        servletRsp.flushBuffer();
04
05        bytesSent += s.length();
06        Log.debug("bytesSent= " + bytesSent);
07        // Log.debug("BCA sent event: " + s);
08    }
09
10    /**
11     * Converts the Java Event to a JavaScript function call in browser page.
12     */
13    protected String event2JavaScript(Event event) throws IOException {
14
15        // Convert the event to a comma-separated string.
16        String jsArgs = "";
17        for (Iterator iter = event.getFieldNames(); iter.hasNext();) {
18            String name = (String) iter.next();
19            String value = event.getField(name);
20            String nextArgument = (jsArgs.equals("") ? "" : ",") + "'" + name + "'" + ", \"" + value + "\"";
21            jsArgs += nextArgument;
22        }
23
24        // Construct and return the function call */
25        return "<script language=\"JavaScript\">parent.push(" + jsArgs + ");</script>";
26    }
27
28}
29
30/*
31 * $Log: BrowserAdapter.java,v $
32 * Revision 1.6  2007/11/09 13:15:35  justb
33 * add charset=UTF-8 in returned HTTP content types
34 *
35 * Revision 1.5  2006/05/15 11:52:53  justb
36 * updates mainly for AJAX client
37 *
38 * Revision 1.4  2006/05/06 00:10:11  justb
39 * various chgs but not too serious...
40 *
41 * Revision 1.3  2005/02/28 12:45:59  justb
42 * introduced Command class
43 *
44 * Revision 1.2  2005/02/21 11:50:44  justb
45 * ohase1 of refactoring Subscriber into Session/Controller/Subscriber
46 *
47 * Revision 1.1  2005/02/18 10:07:23  justb
48 * many renamings of classes (make names compact)
49 *
50 * Revision 1.12  2005/02/15 13:30:23  justb
51 * changes for Tomcat buffering (now working in tc4 and 5.0)
52 *
53 * Revision 1.11  2005/01/24 22:45:58  justb
54 * getting safari to work
55 *
56 * Revision 1.10  2005/01/18 16:46:27  justb
57 * buffer size setting ignored by tomcat workings
58 *
59 * Revision 1.9  2004/10/24 12:58:18  justb
60 * revised client and test classes for new protocol
61 *
62 * Revision 1.8  2004/09/20 22:01:38  justb
63 * more changes for new protocol
64 *
65 * Revision 1.7  2004/09/03 22:35:37  justb
66 * Almost complete rewrite, just checking in now
67 *
68 * Revision 1.6  2004/08/15 16:00:15  justb
69 * enhancements to pull mode
70 *
71 * Revision 1.5  2004/08/13 23:36:05  justb
72 * rewrite of Pullet into Pushlet "pull" mode
73 *
74 * Revision 1.4  2003/08/15 08:37:40  justb
75 * fix/add Copyright+LGPL file headers and footers
76 *
77 * Revision 1.3  2003/08/12 09:57:05  justb
78 * replaced all print statements to Log.*() calls
79 *
80 * Revision 1.2  2003/05/18 16:15:07  justb
81 * support for XML encoded Events
82 *
83 * Revision 1.1.1.1  2002/09/24 21:02:30  justb
84 * import to sourceforge
85 *
86 * Revision 1.1.1.1  2002/09/20 22:48:17  justb
87 * import to SF
88 *
89 * Revision 1.1.1.1  2002/09/20 14:19:02  justb
90 * first import into SF
91 *
92 * Revision 1.5  2002/04/15 20:42:41  just
93 * reformatting and renaming GuardedQueue to EventQueue
94 *
95 * Revision 1.4  2000/12/27 22:39:35  just
96 * no message
97 *
98 * Revision 1.3  2000/10/30 14:15:47  just
99 * no message
00 *
01 *
02 */
03
04