Source Code Cross Referenced for HTTPConnection.java in  » Ajax » Laszlo-4.0.10 » org » openlaszlo » connection » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » Laszlo 4.0.10 » org.openlaszlo.connection 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* *****************************************************************************
002:         * HTTPConnection.java
003:         * ****************************************************************************/
004:
005:        /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006:         * Copyright 2001-2006 Laszlo Systems, Inc.  All Rights Reserved.              *
007:         * Use is subject to license terms.                                            *
008:         * J_LZ_COPYRIGHT_END *********************************************************/
009:
010:        package org.openlaszlo.connection;
011:
012:        import java.io.IOException;
013:        import java.io.OutputStream;
014:        import java.io.StringReader;
015:        import java.util.Collections;
016:        import java.util.Date;
017:        import java.util.Enumeration;
018:        import java.util.Iterator;
019:        import java.util.List;
020:        import java.util.Properties;
021:        import java.util.Random;
022:        import java.util.Vector;
023:        import javax.servlet.http.HttpSessionBindingListener;
024:        import javax.servlet.http.HttpSessionBindingEvent;
025:        import javax.servlet.http.HttpServletRequest;
026:        import javax.servlet.http.HttpServletResponse;
027:        import javax.servlet.ServletOutputStream;
028:        import org.apache.log4j.Logger;
029:        import org.jdom.Document;
030:        import org.jdom.Element;
031:        import org.jdom.input.SAXBuilder;
032:        import org.jdom.JDOMException;
033:
034:        /** Persistent connection for SWF files. */
035:        public class HTTPConnection {
036:            private static final String CONNECTED = "__LPSCONNECTED";
037:            private static final String RECONNECTED = "__LPSRECONNECTED";
038:
039:            /** Queue to store events */
040:            private List mQueue;
041:
042:            /** Username for connection -- this may not be unique */
043:            private String mUsername;
044:
045:            /** Session id */
046:            private String mSID;
047:
048:            /** Connection id -- changes with each reconnection */
049:            private String mCID;
050:
051:            /** Servlet response object */
052:            private HttpServletResponse mRes;
053:
054:            /** Output stream */
055:            private OutputStream mOut;
056:
057:            /** Flag to immediately flush message queue */
058:            private boolean mDoFlushQueue;
059:
060:            /** Flag to pad headers with bytes. Used for IE, which doesn't display
061:             * anything until byte 2000. */
062:            private boolean mDoPad;
063:
064:            /** Heartbeat interval */
065:            private long mHeartbeatInterval;
066:
067:            /** Heartbeat count */
068:            private int mHeartbeatCount;
069:
070:            /** Request count */
071:            private int mRequestCount;
072:
073:            /** Sent count */
074:            private int mSentCount;
075:
076:            /** Flush count */
077:            private int mFlushCount;
078:
079:            /** Total number of bytes sent out during application session */
080:            private int mTotalNumOfBytes;
081:
082:            /** Number of bytes sent out */
083:            private int mNumOfBytes;
084:
085:            /** String to send out depending on whether it's a connection or
086:             * reconnection */
087:            private String mConnectedString;
088:
089:            private boolean mEmitConnectHeaders = false;
090:
091:            /** Version of SWF bytes for connection messages. */
092:            private int mSWFVersion;
093:
094:            //------------------------------------------------------------
095:            // Statics
096:            //------------------------------------------------------------
097:            private static Logger mLogger = Logger
098:                    .getLogger(HTTPConnection.class);
099:
100:            /** Used to send IE a pad of 2000 spaces. IE doesn't display information
101:             * until it receives 2000 bytes or the connection is closed by the web
102:             * server. */
103:            private static String mPad;
104:
105:            /** Static initializer synchronization lock. */
106:            private static Object mStaticInitLock = new Object();
107:
108:            /** Check for static initialize block. */
109:            private static boolean mDoStaticInit = true;
110:
111:            /** Check if the class was inited (see doInit()). */
112:            private static boolean mDoInit = true;
113:
114:            /** Compiled heartbeat SWF bytes. */
115:            private static byte[] mSWFHeartbeat;
116:
117:            /** Compiled reconnect command SWF bytes. */
118:            private static byte[] mSWFDoReconnect;
119:
120:            /** Maximum length of a message. */
121:            private static int mMaxMessageLen = 2000;
122:
123:            /** Content length of connection SWF. */
124:            private static int mConnectionLength = 65536;
125:
126:            /** Check if disconnect was requested. */
127:            private boolean mDoDisconnect = false;
128:
129:            /** Flag to check if this connection will be replaced by another
130:             * connection. */
131:            private boolean mIsReconnect = false;
132:
133:            /** Interval to wait after client reconnection command is sent. */
134:            private static int mReconnectionWaitInterval = 60000;
135:
136:            /** Count to generate UIDs. */
137:            private static long mUIDCount = 0;
138:
139:            //------------------------------------------------------------
140:            // Not clear whether a static initializer needs to be
141:            // synchronized, but not taking any chances.
142:            //------------------------------------------------------------
143:            static {
144:                if (mDoStaticInit) {
145:                    synchronized (mStaticInitLock) {
146:                        if (mDoStaticInit) {
147:                            StringBuffer buf = new StringBuffer(2000);
148:                            for (int i = 0; i < 2000; i++)
149:                                buf.append(' ');
150:                            mPad = buf.toString();
151:
152:                            mSWFHeartbeat = new SwfByte().actionSetElement(
153:                                    getElement(getConnectionInfoXML("__LPSHB",
154:                                            null))).setShowFrame().getBuf();
155:
156:                            mSWFDoReconnect = new SwfByte().actionSetElement(
157:                                    getElement(getConnectionInfoXML(
158:                                            "__LPSDORECONNECT", null)))
159:                                    .setShowFrame().getBuf();
160:
161:                            mDoStaticInit = false;
162:                        }
163:                    }
164:                }
165:            }
166:
167:            //------------------------------------------------------------
168:            // Initialize static properties. This should only get called 
169:            // once.
170:            //------------------------------------------------------------
171:            synchronized static public void init(Properties properties) {
172:                if (!mDoInit)
173:                    return;
174:
175:                mLogger.debug(
176:                /* (non-Javadoc)
177:                 * @i18n.test
178:                 * @org-mes="init(properties)"
179:                 */
180:                org.openlaszlo.i18n.LaszloMessages.getMessage(
181:                        HTTPConnection.class.getName(), "051018-190"));
182:
183:                Enumeration propNames = properties.propertyNames();
184:                while (propNames.hasMoreElements()) {
185:
186:                    String key = (String) propNames.nextElement();
187:                    String val = properties.getProperty(key);
188:
189:                    try {
190:                        if (val != null) {
191:                            if (key.intern() == "maxMessageLen")
192:                                mMaxMessageLen = Integer.parseInt(val);
193:                            else if (key.intern() == "connectionLength")
194:                                mConnectionLength = Integer.parseInt(val);
195:                            else if (key.intern() == "reconnectionWaitInterval")
196:                                mReconnectionWaitInterval = Integer
197:                                        .parseInt(val);
198:                        }
199:                    } catch (NumberFormatException e) {
200:                        mLogger.debug(e.getMessage());
201:                    }
202:                }
203:
204:                // These are the minimum values.
205:                if (mMaxMessageLen < 2000)
206:                    mMaxMessageLen = 2000;
207:                if (mConnectionLength < (5 * mMaxMessageLen))
208:                    mConnectionLength = 5 * mMaxMessageLen;
209:                if (mReconnectionWaitInterval < 10000) // wait a minimum of 10 seconds
210:                    mReconnectionWaitInterval = 60000; // default 60 seconds
211:
212:                mLogger.debug(
213:                /* (non-Javadoc)
214:                 * @i18n.test
215:                 * @org-mes="maxMessageLen:" + p[0]
216:                 */
217:                org.openlaszlo.i18n.LaszloMessages.getMessage(
218:                        HTTPConnection.class.getName(), "051018-227",
219:                        new Object[] { new Integer(mMaxMessageLen) }));
220:                mLogger.debug(
221:                /* (non-Javadoc)
222:                 * @i18n.test
223:                 * @org-mes="connectionLength:" + p[0]
224:                 */
225:                org.openlaszlo.i18n.LaszloMessages.getMessage(
226:                        HTTPConnection.class.getName(), "051018-235",
227:                        new Object[] { new Integer(mConnectionLength) }));
228:                mDoInit = false;
229:            }
230:
231:            //------------------------------------------------------------
232:            // Constructor
233:            //------------------------------------------------------------
234:
235:            /**
236:             * Generates a unique identifier.
237:             * @return hexadecimal unique string identifier.
238:             */
239:            private synchronized static String generateUID() {
240:                return Long.toHexString(System.currentTimeMillis())
241:                        + Long.toHexString(mUIDCount++);
242:            }
243:
244:            /** 
245:             * Constructor.
246:             *
247:             * @param res http servlet response to use as persistent connection 
248:             * @param username username associated with connection 
249:             */
250:            public HTTPConnection(HttpServletResponse res, String username,
251:                    int swfversion) throws IOException {
252:                mRes = res;
253:                mOut = res.getOutputStream();
254:                mUsername = username;
255:                mSID = generateUID();
256:                mCID = generateUID();
257:                mHeartbeatCount = 0;
258:                mRequestCount = 0;
259:                mSentCount = 0;
260:                mFlushCount = 0;
261:                mTotalNumOfBytes = 0;
262:                mNumOfBytes = 0;
263:                mDoDisconnect = false;
264:                mSWFVersion = swfversion;
265:
266:                // Don't have to make queue thread-safe since synchronization is handled
267:                // below.
268:                mQueue = new Vector();
269:
270:                mConnectedString = CONNECTED;
271:
272:                // This is false when attempting a reconnect with client so messages can
273:                // be saved.
274:                mDoFlushQueue = true;
275:
276:                setDoPad(false);
277:                setHeartbeatInterval(0);
278:            }
279:
280:            /** 
281:             * Will update the request count, heartbeat count, total number of bytes
282:             * sent.
283:             *
284:             * @param res http servlet response to user as persistent connect
285:             * @param hc HTTPConnection to copy parameters from
286:             */
287:            public HTTPConnection(HttpServletResponse res, HTTPConnection hc)
288:                    throws IOException {
289:                mRes = res;
290:                mOut = res.getOutputStream();
291:                mUsername = hc.mUsername;
292:                mSID = hc.mSID;
293:                mCID = generateUID();
294:                mHeartbeatCount += hc.mHeartbeatCount;
295:                mRequestCount += hc.mRequestCount;
296:                mSentCount += hc.mSentCount;
297:                mFlushCount += hc.mFlushCount;
298:                mTotalNumOfBytes += hc.mTotalNumOfBytes;
299:                mEmitConnectHeaders = hc.mEmitConnectHeaders;
300:                mDoDisconnect = false;
301:                mSWFVersion = hc.mSWFVersion;
302:
303:                mConnectedString = RECONNECTED;
304:
305:                // Easy way to save the queue (or is it too easy? I think this is ok...)
306:                mQueue = hc.mQueue;
307:
308:                mNumOfBytes = 0;
309:
310:                // This is false when attempting a reconnect with client so messages can
311:                // be saved.
312:                mDoFlushQueue = true;
313:
314:                setDoPad(hc.mDoPad);
315:                setHeartbeatInterval(hc.mHeartbeatInterval);
316:            }
317:
318:            //------------------------------------------------------------
319:            // Methods
320:            //------------------------------------------------------------
321:
322:            /**
323:             * Queue up event to send. 
324:             *
325:             * @param msg event message
326:             * @param doFlushQueue if true, flushes the message event queue
327:             * @throws IOException if connection does not exist
328:             */
329:            synchronized public void send(String msg) throws IOException {
330:                mLogger.debug(
331:                /* (non-Javadoc)
332:                 * @i18n.test
333:                 * @org-mes="send(msg=" + p[0] + ")"
334:                 */
335:                org.openlaszlo.i18n.LaszloMessages.getMessage(
336:                        HTTPConnection.class.getName(), "051018-353",
337:                        new Object[] { msg }));
338:
339:                if (mDoDisconnect) {
340:                    mLogger.debug(
341:                    /* (non-Javadoc)
342:                     * @i18n.test
343:                     * @org-mes="connection is already disconnected, not sending"
344:                     */
345:                    org.openlaszlo.i18n.LaszloMessages.getMessage(
346:                            HTTPConnection.class.getName(), "051018-363"));
347:                    return;
348:                }
349:
350:                Element element = getElement(msg);
351:                if (element == null) {
352:                    mLogger.debug(
353:                    /* (non-Javadoc)
354:                     * @i18n.test
355:                     * @org-mes="Bad XML for message: " + p[0]
356:                     */
357:                    org.openlaszlo.i18n.LaszloMessages.getMessage(
358:                            HTTPConnection.class.getName(), "051018-376",
359:                            new Object[] { msg }));
360:                    return;
361:                }
362:
363:                byte[] swfBuf = new SwfByte().actionSetElement(element)
364:                        .setShowFrame().getBuf();
365:
366:                if (swfBuf.length > mMaxMessageLen) {
367:                    String info =
368:                    /* (non-Javadoc)
369:                     * @i18n.test
370:                     * @org-mes="compiled message bytes are too large -- greater than" + p[0] + ")"
371:                     */
372:                    org.openlaszlo.i18n.LaszloMessages.getMessage(
373:                            HTTPConnection.class.getName(), "051018-393",
374:                            new Object[] { new Integer(mMaxMessageLen) });
375:                    mLogger.debug(info);
376:                    throw new IOException(info);
377:                }
378:
379:                synchronized (mQueue) {
380:                    mRequestCount++;
381:                    mQueue.add(swfBuf);
382:                }
383:
384:                if (mDoFlushQueue) {
385:                    notify();
386:                }
387:
388:            }
389:
390:            /** 
391:             * Close connection.
392:             */
393:            public void disconnect() {
394:                disconnect(false);
395:            }
396:
397:            /** 
398:             * Close connection.
399:             *
400:             * @param isReconnect if this connection will be replaced by another
401:             * connection.
402:             */
403:            synchronized public void disconnect(boolean isReconnect) {
404:                mLogger.debug("disconnect()");
405:                mIsReconnect = isReconnect;
406:                mDoDisconnect = true;
407:                notify();
408:            }
409:
410:            /**
411:             * Check if connection is to be replaced by another connection.
412:             */
413:            synchronized public boolean toBeReconnected() {
414:                return mIsReconnect;
415:            }
416:
417:            /** 
418:             * This call will block and wait for events to handle. Keeps HTTP
419:             * connection alive for an asynchronous event.
420:             *
421:             * @param res servlet response object 
422:             * @return true if connection was lost to reconnection, else false
423:             */
424:            public void connect() throws IOException {
425:                mLogger.debug("connect()");
426:
427:                try {
428:                    mNumOfBytes += sendHeader();
429:                    mNumOfBytes += flushMessageQueue();
430:
431:                    mTotalNumOfBytes += mNumOfBytes;
432:
433:                    int numOfBytesSent = 0;
434:                    long waitInterval = mHeartbeatInterval;
435:                    long reconnectRequestTime = 0; // time we made reconnect request
436:
437:                    while (true) {
438:
439:                        mLogger.debug(
440:                        /* (non-Javadoc)
441:                         * @i18n.test
442:                         * @org-mes="[" + p[0] + "," + p[1] + "] " + "  request: " + p[2] + "  sent: " + p[3] + ", flush: " + p[4] + ", heartbeats: " + p[5] + ", bytes: " + p[6] + " (" + p[7] + "/" + p[8] + ")"
443:                         */
444:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
445:                                HTTPConnection.class.getName(), "051018-471",
446:                                new Object[] { mUsername, mSID,
447:                                        new Integer(mRequestCount),
448:                                        new Integer(mSentCount),
449:                                        new Integer(mFlushCount),
450:                                        new Integer(mHeartbeatCount),
451:                                        new Integer(mTotalNumOfBytes),
452:                                        new Integer(mNumOfBytes),
453:                                        new Integer(mConnectionLength) }));
454:                        synchronized (this ) {
455:                            wait(waitInterval);
456:                        }
457:
458:                        if (mDoDisconnect) {
459:                            mLogger.debug(
460:                            /* (non-Javadoc)
461:                             * @i18n.test
462:                             * @org-mes="disconnecting..."
463:                             */
464:                            org.openlaszlo.i18n.LaszloMessages.getMessage(
465:                                    HTTPConnection.class.getName(),
466:                                    "051018-484"));
467:                            if (reconnectRequestTime != 0) {
468:                                mLogger.debug(
469:                                /* (non-Javadoc)
470:                                 * @i18n.test
471:                                 * @org-mes="reconnect time: " + p[0] + "ms"
472:                                 */
473:                                org.openlaszlo.i18n.LaszloMessages.getMessage(
474:                                        HTTPConnection.class.getName(),
475:                                        "051018-493",
476:                                        new Object[] { new Long(new Date()
477:                                                .getTime()
478:                                                - reconnectRequestTime) }));
479:                            }
480:                            return;
481:                        }
482:
483:                        // Check to see if we're nearing the limit of bytes sent out
484:                        if (doReconnect()) {
485:
486:                            mLogger.debug(
487:                            /* (non-Javadoc)
488:                             * @i18n.test
489:                             * @org-mes="sending reconnect request " + p[0] + "..."
490:                             */
491:                            org.openlaszlo.i18n.LaszloMessages.getMessage(
492:                                    HTTPConnection.class.getName(),
493:                                    "051018-508", new Object[] { mUsername }));
494:
495:                            if (reconnectRequestTime == 0) {
496:                                // ...give client a few seconds to reconnect...
497:                                waitInterval = mReconnectionWaitInterval;
498:
499:                                synchronized (this ) {
500:                                    mDoFlushQueue = false;
501:                                }
502:
503:                                mLogger.debug(
504:                                /* (non-Javadoc)
505:                                 * @i18n.test
506:                                 * @org-mes="...for " + p[0] + " seconds"
507:                                 */
508:                                org.openlaszlo.i18n.LaszloMessages.getMessage(
509:                                        HTTPConnection.class.getName(),
510:                                        "051018-525", new Object[] { new Long(
511:                                                waitInterval / 1000) }));
512:
513:                                // ...send reconnect request to client
514:                                mOut.write(mSWFDoReconnect);
515:                                mOut.flush();
516:
517:                                mNumOfBytes += mSWFDoReconnect.length;
518:                                mTotalNumOfBytes += mSWFDoReconnect.length;
519:
520:                                reconnectRequestTime = new Date().getTime();
521:                                continue;
522:
523:                            }
524:
525:                            // If our wait is less than the wait interval, keep
526:                            // waiting...
527:                            long now = new Date().getTime();
528:                            long interval = now - reconnectRequestTime;
529:                            if (interval < waitInterval) {
530:                                mLogger.debug(
531:                                /* (non-Javadoc)
532:                                 * @i18n.test
533:                                 * @org-mes="still waiting for reconnect..."
534:                                 */
535:                                org.openlaszlo.i18n.LaszloMessages.getMessage(
536:                                        HTTPConnection.class.getName(),
537:                                        "051018-551"));
538:                                continue;
539:                            }
540:
541:                            // ...else, really quit.
542:                            mLogger.debug(
543:                            /* (non-Javadoc)
544:                             * @i18n.test
545:                             * @org-mes="interval was " + p[0] + "; done waiting...goodbye!"
546:                             */
547:                            org.openlaszlo.i18n.LaszloMessages.getMessage(
548:                                    HTTPConnection.class.getName(),
549:                                    "051018-563", new Object[] { new Long(
550:                                            interval) }));
551:                            return;
552:                        }
553:
554:                        numOfBytesSent = 0;
555:
556:                        // If queue is 0, just send heartbeat.
557:                        if (mQueue.size() == 0) {
558:                            mHeartbeatCount++;
559:                            mOut.write(mSWFHeartbeat);
560:                            mOut.flush();
561:                            numOfBytesSent = mSWFHeartbeat.length;
562:                        } else {
563:                            numOfBytesSent = flushMessageQueue();
564:                        }
565:
566:                        mNumOfBytes += numOfBytesSent;
567:                        mTotalNumOfBytes += numOfBytesSent;
568:                    }
569:                } catch (InterruptedException e) {
570:                    mLogger.debug(
571:                    /* (non-Javadoc)
572:                     * @i18n.test
573:                     * @org-mes="InterruptedException: " + p[0]
574:                     */
575:                    org.openlaszlo.i18n.LaszloMessages.getMessage(
576:                            HTTPConnection.class.getName(), "051018-590",
577:                            new Object[] { e.getMessage() }));
578:                }
579:            }
580:
581:            /**
582:             * @return true if reconnect needs to happen.
583:             */
584:            private boolean doReconnect() {
585:                return doReconnect(0);
586:            }
587:
588:            /**
589:             * @param n number of potential bytes that will be going out.
590:             * @return true if reconnect needs to happen.
591:             */
592:            private boolean doReconnect(int n) {
593:                return (mConnectionLength - (mMaxMessageLen * 2)) <= (mNumOfBytes + n);
594:            }
595:
596:            /** 
597:             * Send a connection header and flush any messages in the queue, if any.
598:             */
599:            private int sendHeader() throws InterruptedException, IOException {
600:                mLogger.debug(
601:                /* (non-Javadoc)
602:                 * @i18n.test
603:                 * @org-mes="sendHeader()"
604:                 */
605:                org.openlaszlo.i18n.LaszloMessages.getMessage(
606:                        HTTPConnection.class.getName(), "051018-626"));
607:
608:                // Content-length used to be commented out because w/Tomcat 3.3
609:                // connections seemed open to the servlet container even after browser
610:                // close.
611:                mRes.setContentLength(mConnectionLength);
612:                mRes.setContentType("application/x-shockwave-flash");
613:
614:                // This is to keep browsers from doing connection keep-alives.
615:                mRes.setHeader("Connection", "close");
616:                mRes.setHeader("Keep-Alive", "close");
617:
618:                if (mEmitConnectHeaders) {
619:                    if (mConnectedString == CONNECTED)
620:                        mRes.setHeader("X-LPS-C", mCID);
621:                    else if (mConnectedString == RECONNECTED)
622:                        mRes.setHeader("X-LPS-R", mCID);
623:                }
624:
625:                mLogger.debug("Sent connected string: " + mConnectedString);
626:
627:                String info;
628:                if (mConnectedString == CONNECTED) {
629:                    info = getConnectionInfoXML(mConnectedString, "<cid>"
630:                            + mCID + "</cid>" + "<sid>" + mSID + "</sid>"
631:                            + "<usr>" + mUsername + "</usr>");
632:                } else {
633:                    info = getConnectionInfoXML(mConnectedString, "<cid>"
634:                            + mCID + "</cid>");
635:
636:                }
637:                SwfByte swf = new SwfByte();
638:
639:                swf.setHeader(mSWFVersion);
640:                swf.setLength(mConnectionLength);
641:                swf.actionSetElement(getElement(info));
642:                if (mDoPad)
643:                    swf.actionSetVariable("pad", mPad);
644:                swf.setShowFrame();
645:
646:                byte[] buf = swf.getBuf();
647:                mOut.write(buf, 0, buf.length);
648:                mOut.flush();
649:
650:                return buf.length;
651:            }
652:
653:            /** 
654:             * Flush out messages in queue for the client.
655:             *
656:             * @return number of messages sent
657:             * @throws IOException if there's a problem with the output stream
658:             */
659:            private int flushMessageQueue() throws IOException,
660:                    InterruptedException {
661:                mLogger.debug(
662:                /* (non-Javadoc)
663:                 * @i18n.test
664:                 * @org-mes="flushMessageQueue()"
665:                 */
666:                org.openlaszlo.i18n.LaszloMessages.getMessage(
667:                        HTTPConnection.class.getName(), "051018-690"));
668:
669:                byte[] swfBuf;
670:                int numOfBytes = 0;
671:                synchronized (mQueue) {
672:
673:                    Iterator iter = mQueue.iterator();
674:                    if (!iter.hasNext())
675:                        return 0;
676:
677:                    while (iter.hasNext()) {
678:                        swfBuf = (byte[]) iter.next();
679:                        mOut.write(swfBuf);
680:                        numOfBytes += swfBuf.length;
681:                        ++mSentCount;
682:                        iter.remove();
683:
684:                        // If data sent is above the byte limit, reconnect before
685:                        // flushing the rest of the queue.
686:                        if (doReconnect(numOfBytes))
687:                            break;
688:                    }
689:
690:                    mOut.flush();
691:                    ++mFlushCount;
692:                }
693:
694:                return numOfBytes;
695:            }
696:
697:            /** 
698:             * Check if padding is required.
699:             */
700:            public boolean doPad() {
701:                return mDoPad;
702:            }
703:
704:            /** 
705:             * Set if you want padding of bytes to headers. Used for browser like IE
706:             * that don't display anything until the Nth byte.
707:             *
708:             * @param doPad flag for padding
709:             * @return this object
710:             */
711:            public HTTPConnection setDoPad(boolean doPad) {
712:                mDoPad = doPad;
713:                return this ;
714:            }
715:
716:            /** 
717:             * Get heartbeat interval in milliseconds.
718:             */
719:            public long getHeartbeatInterval() {
720:                return mHeartbeatInterval;
721:            }
722:
723:            /**
724:             * @return version for SWF bytes.
725:             */
726:            public int getSWFVersion() {
727:                return mSWFVersion;
728:            }
729:
730:            /** 
731:             * Set heartbeat in milliseconds.
732:             */
733:            public HTTPConnection setHeartbeatInterval(long heartbeatInterval) {
734:                mHeartbeatInterval = heartbeatInterval;
735:                return this ;
736:            }
737:
738:            /** 
739:             * Get username.
740:             */
741:            public String getUsername() {
742:                return mUsername;
743:            }
744:
745:            /** 
746:             * Get unique id.
747:             */
748:            public String getCID() {
749:                return mCID;
750:            }
751:
752:            /**
753:             */
754:            public HTTPConnection setEmitConnectHeaders(
755:                    boolean emitConnectHeaders) {
756:                mEmitConnectHeaders = emitConnectHeaders;
757:                return this ;
758:            }
759:
760:            /** 
761:             * Turn xml into a JDOM element.
762:             *
763:             * @param xml xml string
764:             * @return JDOM element
765:             */
766:            private static Element getElement(String xml) {
767:                Element el = null;
768:                try {
769:                    el = new SAXBuilder(false).build(new StringReader(xml))
770:                            .getRootElement();
771:                } catch (JDOMException e) {
772:                    mLogger.debug(e.getMessage());
773:                } catch (IOException e) {
774:                    mLogger.debug(e.getMessage());
775:                }
776:                return el;
777:            }
778:
779:            /** 
780:             * XML message structure used to push server information to the
781:             * client. Used for heartbeats, sending connection startup and informing
782:             * users someone's been disconnected.
783:             *
784:             * @param type type of information. This will be received by the client as a
785:             * dataset.
786:             * @param msg message of type, if any
787:             * @return an xml string with connection information
788:             */
789:            public static String getConnectionInfoXML(String type, String msg) {
790:                if (msg == null)
791:                    return "<resultset s=\"0\"><root dset=\"" + type
792:                            + "\" /></resultset>";
793:                else
794:                    return "<resultset s=\"0\"><root dset=\"" + type + "\">"
795:                            + msg + "</root></resultset>";
796:            }
797:
798:            public static int getMaxMessageLen() {
799:                return mMaxMessageLen;
800:            }
801:
802:            public static int getConnectionLength() {
803:                return mConnectionLength;
804:            }
805:
806:            public static int getReconnectionWaitInterval() {
807:                return mReconnectionWaitInterval;
808:            }
809:
810:            public String toString() {
811:                return new StringBuffer().append("<connection").append(
812:                        " sid=\"").append(mSID).append("\"").append(" cid=\"")
813:                        .append(mCID).append("\"").append(" user=\"").append(
814:                                mUsername).append("\"")
815:                        .append(" heartbeats=\"").append(mHeartbeatCount)
816:                        .append("\"").append(" flushes=\"").append(mFlushCount)
817:                        .append("\"").append(" current-bytes=\"").append(
818:                                mNumOfBytes).append("\"").append(
819:                                " total-bytes=\"").append(mTotalNumOfBytes)
820:                        .append("\"").append(" />").toString();
821:            }
822:
823:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.