KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > echo2example > chatclient > ChatApp


1 /*
2  * This file is part of the Echo Web Application Framework (hereinafter "Echo").
3  * Copyright (C) 2002-2005 NextApp, Inc.
4  *
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * Alternatively, the contents of this file may be used under the terms of
18  * either the GNU General Public License Version 2 or later (the "GPL"), or
19  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20  * in which case the provisions of the GPL or the LGPL are applicable instead
21  * of those above. If you wish to allow use of your version of this file only
22  * under the terms of either the GPL or the LGPL, and not to allow others to
23  * use your version of this file under the terms of the MPL, indicate your
24  * decision by deleting the provisions above and replace them with the notice
25  * and other provisions required by the GPL or the LGPL. If you do not delete
26  * the provisions above, a recipient may use your version of this file under
27  * the terms of any one of the MPL, the GPL or the LGPL.
28  */

29
30 package echo2example.chatclient;
31
32 import java.io.IOException JavaDoc;
33
34 import nextapp.echo2.app.ApplicationInstance;
35 import nextapp.echo2.app.TaskQueueHandle;
36 import nextapp.echo2.app.Window;
37 import nextapp.echo2.app.event.ActionEvent;
38 import nextapp.echo2.app.event.ActionListener;
39 import nextapp.echo2.webcontainer.ContainerContext;
40
41 /**
42  * Chat Client <code>ApplicationInstance</code> implementation.
43  */

44 public class ChatApp extends ApplicationInstance {
45
46     /**
47      * Returns the active <code>ChatApp</code>.
48      *
49      * @return the active <code>ChatApp</code>
50      */

51     public static ChatApp getApp() {
52         return (ChatApp) getActive();
53     }
54     
55     private ChatSession chatSession;
56     private TaskQueueHandle incomingMessageQueue;
57     
58     // Auto-logout times set very short for demonstration purposes.
59
private static final int POST_INTERVAL_AUTO_LOGOUT_WARNING = 2 * 60 * 1000; // 2 minutes
60
private static final int POST_INTERVAL_AUTO_LOGOUT = 3 * 60 * 1000; // 3 minutes
61

62     private long lastActionTime;
63     private long lastPostTime;
64     private int pollingInterval = 1000;
65     
66     private MessageDialog logoutWarningDialog;
67     
68     /**
69      * Calculates the appropriate client-server polling interval based on the
70      * delta between the current time and the last interesting event (i.e.
71      * posted message in the chat) which occurred.
72      *
73      * @return the appropriate polling interval
74      */

75     private int calculatePollingInterval() {
76         long delta = System.currentTimeMillis() - lastActionTime;
77         if (delta < 10 * 1000) {
78             // Last action 0-10 seconds ago: 1 second poll update intervals.
79
return 1000;
80         } else if (delta < 20 * 1000) {
81             // Last action 10-20 seconds ago: 2 second poll update intervals.
82
return 2000;
83         } else if (delta < 30 * 1000) {
84             // Last action 20-30 seconds ago: 3 second poll update intervals.
85
return 3000;
86         } else if (delta < 60 * 1000) {
87             // Last action 30-60 seconds ago: 5 second poll update intervals.
88
return 5000;
89         } else {
90             // Last action > 60 seconds ago: 10 second poll update intervals.
91
return 10000;
92         }
93     }
94     
95     /**
96      * Attempts to connect to the chat server with the specified user name.
97      * Displays a <code>ChatScreen</code> for the user if the user
98      * is successfully connected. Performs no action if the user is not
99      * successfully connected.
100      *
101      * @return true if the operation was successfully completed,
102      * false otherwise
103      */

104     public boolean connect(String JavaDoc userName) {
105         try {
106             chatSession = ChatSession.forUserName(userName);
107         } catch (IOException JavaDoc ex) {
108             throw new RuntimeException JavaDoc(ex);
109         }
110         if (chatSession == null) {
111             return false;
112         } else {
113             if (incomingMessageQueue != null) {
114                 throw new IllegalStateException JavaDoc();
115             }
116             incomingMessageQueue = createTaskQueue();
117             updatePollingInterval(true);
118             lastPostTime = System.currentTimeMillis();
119             
120             getDefaultWindow().setContent(new ChatScreen());
121             return true;
122         }
123     }
124     
125     /**
126      * Disconnects from the chat server and logs the current user out.
127      * Displays the <code>LoginScreen</code>.
128      */

129     public void disconnect() {
130         try {
131             chatSession.dispose();
132             chatSession = null;
133             if (incomingMessageQueue != null) {
134                 removeTaskQueue(incomingMessageQueue);
135                 incomingMessageQueue = null;
136             }
137             logoutWarningDialog = null;
138             getDefaultWindow().setContent(new LoginScreen());
139         } catch (IOException JavaDoc ex) {
140             throw new RuntimeException JavaDoc(ex);
141         }
142     }
143     
144     /**
145      * Retrieves new messages from the <code>ChatSession</code>.
146      * Once the new messages are deleted they are removed from the queue of
147      * 'new' messages.
148      * Invoking this method thus alters the state of the new message queue.
149      *
150      * @return an array of new messages
151      */

152     public ChatSession.Message[] getNewMessages() {
153         return chatSession.getNewMessages();
154     }
155     
156     /**
157      * Returns the user name of the currently logged-in user.
158      *
159      * @return the user name
160      */

161     public String JavaDoc getUserName() {
162         return chatSession == null ? null : chatSession.getUserName();
163     }
164     
165     /**
166      * The <code>hasQueuedTasks()</code> method has been overridden such that we
167      * can perform checks at every polling interval. Alternatively tasks could
168      * be added using threads running in the background, but for compliance
169      * with earlier versions of the J2EE specification which do not allow
170      * multi-threading, such work is accomplished in this method.
171      *
172      * @see nextapp.echo2.app.ApplicationInstance#hasQueuedTasks()
173      */

174     public boolean hasQueuedTasks() {
175         // Poll server and determine if any new messages have been posted.
176
if (pollServer()) {
177             // Add new messages to ChatScreen.
178
final ChatScreen chatScreen = (ChatScreen) getDefaultWindow().getContent();
179             enqueueTask(incomingMessageQueue, new Runnable JavaDoc(){
180                 public void run() {
181                     chatScreen.updateMessageList();
182                     updatePollingInterval(true);
183                 }
184             });
185         }
186         
187         // Determine if the polling interval should be updated, and if
188
// necessary, queue a task to update it.
189
if (pollingInterval != calculatePollingInterval()) {
190             enqueueTask(incomingMessageQueue, new Runnable JavaDoc() {
191                 public void run() {
192                     updatePollingInterval(false);
193                 }
194             });
195         }
196         
197         if (System.currentTimeMillis() - lastPostTime > POST_INTERVAL_AUTO_LOGOUT) {
198             // If the user has not posted any messages in a period of
199
// time, automatically log the user out.
200
enqueueTask(incomingMessageQueue, new Runnable JavaDoc() {
201                 public void run() {
202                     disconnect();
203                 }
204             });
205         } else if (System.currentTimeMillis() - lastPostTime > POST_INTERVAL_AUTO_LOGOUT_WARNING) {
206             // If the user has not posted any messages in a period of
207
// time, raise a dialog box to warn him/her that s/he may
208
// soon be automatically logged out.
209
enqueueTask(incomingMessageQueue, new Runnable JavaDoc() {
210                 public void run() {
211                     if (logoutWarningDialog == null) {
212                         logoutWarningDialog = new MessageDialog(Messages.getString("AutoLogoutWarningDialog.Title"),
213                                 Messages.getString("AutoLogoutWarningDialog.Message"), MessageDialog.TYPE_CONFIRM,
214                                 MessageDialog.CONTROLS_OK);
215                         getDefaultWindow().getContent().add(logoutWarningDialog);
216                         logoutWarningDialog.addActionListener(new ActionListener() {
217                         
218                             /**
219                              * Reset last post time if user engages the dialog.
220                              *
221                              * @see nextapp.echo2.app.event.ActionListener#actionPerformed(nextapp.echo2.app.event.ActionEvent)
222                              */

223                             public void actionPerformed(ActionEvent e) {
224                                 lastPostTime = System.currentTimeMillis();
225                                 logoutWarningDialog = null;
226                             }
227                         });
228                     }
229                 }
230             });
231         }
232         
233         return super.hasQueuedTasks();
234     }
235     
236     /**
237      * @see nextapp.echo2.app.ApplicationInstance#init()
238      */

239     public Window init() {
240         setStyleSheet(Styles.DEFAULT_STYLE_SHEET);
241         Window window = new Window();
242         window.setTitle(Messages.getString("Application.Title.Window"));
243         window.setContent(new LoginScreen());
244         return window;
245     }
246     
247     /**
248      * Polls the <code>Server</code> to determine if any new messages are
249      * present.
250      *
251      * @return true if any new messages are present
252      */

253     private boolean pollServer() {
254         if (chatSession == null) {
255             return false;
256         }
257         try {
258             chatSession.pollServer();
259             return chatSession.hasNewMessages();
260         } catch (IOException JavaDoc ex) {
261             throw new RuntimeException JavaDoc(ex);
262         }
263     }
264     
265     /**
266      * Posts a message to the chat server for the logged-in user.
267      *
268      * @param content the content of the message to post
269      */

270     public void postMessage(String JavaDoc content) {
271         try {
272             chatSession.postMessage(content);
273             updatePollingInterval(true);
274             lastPostTime = System.currentTimeMillis();
275         } catch (IOException JavaDoc ex) {
276             throw new RuntimeException JavaDoc(ex);
277         }
278     }
279     
280     /**
281      * Updates the client-server polling interval based on the time since
282      * the last event of interest. The interval is increased when nothing
283      * interesting appears to be occurring.
284      *
285      * @param reset flag indicating whether an action has occurred, if true,
286      * the current time will be marked as the time of the last action
287      * and used in future calculations of polling interval.
288      */

289     private void updatePollingInterval(boolean reset) {
290         if (reset) {
291             lastActionTime = System.currentTimeMillis();
292         }
293         pollingInterval = calculatePollingInterval();
294         ContainerContext containerContext = (ContainerContext) getContextProperty(
295                 ContainerContext.CONTEXT_PROPERTY_NAME);
296         containerContext.setTaskQueueCallbackInterval(incomingMessageQueue, pollingInterval);
297     }
298 }
299
Popular Tags