KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icesoft > applications > faces > auctionMonitor > beans > UserBean


1 /*
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * "The contents of this file are subject to the Mozilla Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
11  * License for the specific language governing rights and limitations under
12  * the License.
13  *
14  * The Original Code is ICEfaces 1.5 open source software code, released
15  * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
16  * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
17  * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
18  *
19  * Contributor(s): _____________________.
20  *
21  * Alternatively, the contents of this file may be used under the terms of
22  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
23  * License), in which case the provisions of the LGPL License are
24  * applicable instead of those above. If you wish to allow use of your
25  * version of this file only under the terms of the LGPL License and not to
26  * allow others to use your version of this file under the MPL, indicate
27  * your decision by deleting the provisions above and replace them with
28  * the notice and other provisions required by the LGPL License. If you do
29  * not delete the provisions above, a recipient may use your version of
30  * this file under either the MPL or the LGPL License."
31  *
32  */

33
34 package com.icesoft.applications.faces.auctionMonitor.beans;
35
36 import com.icesoft.applications.faces.auctionMonitor.ChatState;
37 import com.icesoft.applications.faces.auctionMonitor.Message;
38 import com.icesoft.applications.faces.auctionMonitor.MessageLog;
39 import com.icesoft.faces.async.render.OnDemandRenderer;
40 import com.icesoft.faces.async.render.RenderManager;
41 import com.icesoft.faces.async.render.Renderable;
42 import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
43 import com.icesoft.faces.webapp.xmlhttp.RenderingException;
44 import org.apache.commons.logging.Log;
45 import org.apache.commons.logging.LogFactory;
46
47 import javax.faces.context.ExternalContext;
48 import javax.faces.context.FacesContext;
49 import java.net.MalformedURLException JavaDoc;
50 import java.net.URL JavaDoc;
51 import java.util.Map JavaDoc;
52
53 /**
54  * Bean class used to store user information, as well as local information for
55  * messages and viewing information
56  */

57 public class UserBean implements Renderable {
58     private static final String JavaDoc DEFAULT_NICK = "Anonymous";
59     private static final String JavaDoc MINIMIZE_IMAGE =
60             "./images/button_triangle_close.gif";
61     private static final String JavaDoc MAXIMIZE_IMAGE =
62             "./images/button_triangle_open.gif";
63     private static final int NUM_MESSAGES =
64             4; // Number of messages to display at once, default = 4
65
private static final int FLOOD_CAP =
66             500; // Minimum number of milliseconds between sent messages, default = 500
67

68     private static final String JavaDoc MESSAGE_SEND = "send";
69
70     private static final ChatState chatState = ChatState.getInstance();
71     private static Log log = LogFactory.getLog(UserBean.class);
72
73     private OnDemandRenderer renderer = null;
74     private PersistentFacesState persistentState =
75             PersistentFacesState.getInstance();
76     private ExternalContext externalContext =
77             FacesContext.getCurrentInstance().getExternalContext();
78     private String JavaDoc autoLoad = " ";
79     private String JavaDoc message = "";
80     private String JavaDoc color = ChatState.DEFAULT_COLOR;
81     private String JavaDoc nick = DEFAULT_NICK;
82     private String JavaDoc buttonImage = MINIMIZE_IMAGE; // path to button image
83
private MessageLog messageLog = getMessageLog();
84     private Message[] pageLog = new Message[NUM_MESSAGES];
85     private long lastMessageTime = System.currentTimeMillis();
86     private int position = 0;
87     private boolean minimized = true; // true = start minimized (default)
88
private boolean inConversation = false; // render flag to setup chat header
89
// false = have not handled initialization (default)
90
private boolean leaving =
91             false; // flag to track whether the user has left or not
92
// this is used to stop old messages from being submit
93
// when pressing "Leave Chat"
94

95     public boolean isMinimized() {
96         return (minimized);
97     }
98
99     public boolean getConversationStatus() {
100         return (inConversation);
101     }
102     
103     public String JavaDoc getColor() {
104         return (color);
105     }
106
107     public String JavaDoc getMessage() {
108         return (message);
109     }
110
111     public String JavaDoc getButtonImage() {
112         return (buttonImage);
113     }
114
115     public String JavaDoc getNick() {
116         return (nick);
117     }
118
119     public String JavaDoc getNickFormatted() {
120         return (nick + ": ");
121     }
122
123     public String JavaDoc getAutoLoad() {
124         if (this.autoLoad.equals(" ")) {
125             this.autoLoad = "UserBean-Loaded";
126         }
127         return (this.autoLoad);
128     }
129
130     public String JavaDoc getChatStatus() {
131         int numParticipants = chatState.getNumParticipants();
132         if (numParticipants > 1) {
133             return ("Chatting as " + nick + " (" + numParticipants +
134                     " users online)");
135         }
136         return ("Chatting as " + nick + " (" + numParticipants +
137                 " user online)");
138     }
139
140     private Message getMessageAt(int index) {
141         // Check for a valid index, then return the message at the index
142
if ((index < messageLog.size()) && (index >= 0)) {
143             return ((Message) messageLog.get(index));
144         }
145         return (null);
146     }
147
148     private MessageLog getMessageLog() {
149         // Get the message log from the faces context
150
Map JavaDoc applicationMap = externalContext.getApplicationMap();
151         messageLog = (MessageLog) applicationMap.get(LogBean.LOG_PATH);
152
153         // Null messageLog means the LogBean is null, so create it and get the log again
154
if (messageLog == null) {
155             messageLog = LogBean.getInstance().storeMessageLog();
156         }
157
158         return (messageLog);
159     }
160
161     public Message[] getPageLog() {
162         // Fill the array used in the page data table with messages relevant to current position
163
for (int i = 0; i < NUM_MESSAGES; i++) {
164             pageLog[i] = getMessageAt(position - (NUM_MESSAGES - i - 1));
165         }
166
167         return (pageLog);
168     }
169
170     public void setMessage(String JavaDoc pageMessage) {
171         if (!leaving) {
172             addMessage(pageMessage);
173         }
174     }
175
176     public void setNick(String JavaDoc nick) {
177         // Remove and HTML tags and trim the nick
178
nick = cleanTags(nick).trim();
179
180         // Check that the length is between 0 and 20
181
if (nick.length() <= 0) {
182             nick = DEFAULT_NICK;
183         } else if (nick.length() > 20) {
184             nick = nick.substring(0, 20);
185         }
186
187         // Assign the nick and enter the conversation
188
this.nick = nick;
189         enterConversation();
190     }
191     
192     public void setColor(String JavaDoc color) {
193         this.color = color;
194     }
195
196     /**
197      * Method to add the current message variable to the messageLog
198      *
199      * @param toAdd
200      * @return String "send" to be used by JSF action if needed
201      */

202     private String JavaDoc addMessage(String JavaDoc toAdd) {
203         // Check if the message is null or empty
204
if ((toAdd == null) || (toAdd.trim().length() == 0)) {
205             message = "";
206             return MESSAGE_SEND;
207         }
208
209         // Check if the flood cap is exceeded (the user is spamming the channel)
210
if ((System.currentTimeMillis() - lastMessageTime) < FLOOD_CAP) {
211             lastMessageTime = System.currentTimeMillis();
212             message = "";
213             return MESSAGE_SEND;
214         }
215
216         // Trim length, remove tags and check for URL linkage
217
toAdd = trimLength(toAdd);
218         toAdd = cleanTags(toAdd);
219         toAdd = urlRecognize(toAdd);
220
221         // Add the message, update the log, and reset the last send time
222
messageLog.addMessage(nick, toAdd, color);
223         lastMessageTime = System.currentTimeMillis();
224         message = "";
225         updateMessageLog();
226
227         return MESSAGE_SEND;
228     }
229
230     /**
231      * Method to trim the user message after it exceeds a maximum length The
232      * length cap is 150 characters
233      *
234      * @param trim message to trim
235      * @return String the trimmed message
236      */

237     private String JavaDoc trimLength(String JavaDoc trim) {
238         if (trim.length() > 150) {
239             trim = (trim.substring(0, 150) + "...");
240         }
241
242         return trim;
243     }
244
245     /**
246      * Method to remove any tags the user may have put in the passed string An
247      * example of a troublesome tag would be a closing div tag as a nickname
248      *
249      * @param clean to clean of tags
250      * @return String the cleaned and trimmed result
251      */

252     private String JavaDoc cleanTags(String JavaDoc clean) {
253         clean = clean.replaceAll("<", "&lt;");
254         clean = clean.replaceAll(">", "&gt;");
255         clean = clean.replaceAll("&", "&amp;");
256
257         return (clean);
258     }
259
260     /**
261      * Method to recognize and URLs anywhere in the message and pad them with an
262      * href link tag
263      *
264      * @param pad to check and pad
265      * @return String padded
266      */

267     private String JavaDoc urlRecognize(String JavaDoc pad) {
268         int index = pad.indexOf("http://");
269
270         // Quick check to see if pad could possibly be a URL
271
if (index == -1) {
272             return (pad);
273         }
274
275         // Variables for possible text before / after the URL
276
String JavaDoc before, after = "";
277
278         // Try to cast pad as a URL
279
URL JavaDoc checker;
280         try {
281             // Get the index of the first space after the URL
282
int spaceIndex = pad.indexOf(" ", index);
283
284             before = pad.substring(0, index);
285             if (spaceIndex != -1) {
286                 after = pad.substring(spaceIndex, pad.length());
287             }
288             if (spaceIndex != -1) {
289                 pad = pad.substring(index, spaceIndex);
290             } else {
291                 pad = pad.substring(index);
292             }
293             checker = new URL JavaDoc(pad);
294         } catch (MalformedURLException JavaDoc mue) {
295             return pad;
296         }
297
298         // Pad is a valid URL, so add html link tags and return
299
pad = checker.toString();
300         pad = ("<A HREF=\"" + pad + "\" target=\"_blank\">" + pad + "</A>");
301         pad = before + pad + after;
302         return (pad);
303     }
304
305     /**
306      * Method to return the bottom position of the log
307      *
308      * @return int bottom of log (size-1)
309      */

310     private int bottom() {
311         if (messageLog != null) {
312             return (messageLog.size() - 1);
313         }
314         return 0;
315     }
316
317     /**
318      * Method to handle initialization of entering the conversation Add this
319      * UserBean to the ChatState Send a join conversation message
320      */

321     public void enterConversation() {
322         chatState.addUserChild(this);
323         buttonImage = MAXIMIZE_IMAGE;
324         minimized = false;
325         position = bottom();
326         inConversation = true;
327       leaving = false;
328     }
329
330     /**
331      * Method to remove this user from the conversation and reset their status
332      * flag
333      */

334     public void leaveConversation() {
335         leaving = true;
336         inConversation = false;
337         buttonImage = MINIMIZE_IMAGE;
338         minimized = true;
339         chatState.removeUserChild(this);
340     }
341
342     /**
343      * Method to move the user's view upwards by a single line, by setting each
344      * message to the one above it in the log
345      *
346      * @return String "moveUpMinor" to be used by JSF action if needed
347      */

348     public String JavaDoc moveUpMinor() {
349         if ((position - 1) - (NUM_MESSAGES - 1) >= 0) {
350             position--;
351         }
352
353         return ("moveUpMinor");
354     }
355
356     /**
357      * Method to move the user's view downwards by a single line, by setting
358      * each message to the one below it in the log
359      *
360      * @return String "moveDownMinor" to be used by JSF action if needed
361      */

362     public String JavaDoc moveDownMinor() {
363         if (messageLog.size() > (position + 1)) {
364             position++;
365         }
366
367         return ("moveDownMinor");
368     }
369
370     /**
371      * Method to move the user's view to the top of the log (if necessary)
372      *
373      * @return String "moveToTop" to be used by JSF action if needed
374      */

375     public String JavaDoc moveToTop() {
376         if (position >= NUM_MESSAGES) {
377             position = (NUM_MESSAGES - 1);
378         }
379
380         return ("moveToTop");
381     }
382
383     /**
384      * Method to move the user's view to the bottom of the log
385      *
386      * @return String "moveToBottom" to be used by JSF action if needed
387      */

388     public String JavaDoc moveToBottom() {
389         position = bottom();
390
391         return ("moveToBottom");
392     }
393
394     /**
395      * Method to switch the minimized / maximized state of the chat
396      *
397      * @return String "switchMinimized" to be used by JSF action if needed
398      */

399     public String JavaDoc switchMinimized() {
400         minimized = !minimized;
401
402         // Change the image based on the new status, and reRender the page
403
if (minimized) {
404             buttonImage = MINIMIZE_IMAGE;
405         } else {
406             buttonImage = MAXIMIZE_IMAGE;
407             position = bottom();
408         }
409         reRender();
410
411         return ("switchMinimized");
412     }
413
414     /**
415      * Method to tell the chat state to update everyone in the chat This method
416      * is normally called when a message is added to the log
417      */

418     private void updateMessageLog() {
419         chatState.updateAll();
420         position = bottom();
421     }
422
423     /**
424      * Method to get the current state and render the page again This method is
425      * called whenever the messageLog is updated through updateMessageLog() The
426      * updateMessageLog method causes the updateAll method to be called on the
427      * current state Inside the updateAll method is a call to this reRender
428      * method For scalability purposes, this method now uses the
429      * OnDemandRenderer The user viewpoint is always moved to the bottom of the
430      * latest log
431      */

432     public void reRender() {
433         position = bottom();
434
435         if (renderer != null) {
436             renderer.requestRender();
437         } else {
438             if (log.isDebugEnabled()) {
439                 log.debug("OnDemandRenderer was not available (it was null)");
440             }
441         }
442     }
443
444     /**
445      * Method to set the render manager, which should come from
446      * faces-config.xml
447      *
448      * @param manager manager to use
449      */

450     public void setRenderManager(RenderManager manager) {
451         if (manager != null) {
452             renderer = manager.getOnDemandRenderer(AuctionBean.RENDERER_NAME);
453             renderer.add(this);
454         }
455     }
456
457     /**
458      * Method to get the render manager, just return null to satisfy WAS
459      */

460     public RenderManager getRenderManager() {
461         return null;
462     }
463
464     /**
465      * Method to return the current persistent faces state This is used by the
466      * enterprise render manager
467      *
468      * @return PersistentFacesState to use
469      */

470     public PersistentFacesState getState() {
471         return persistentState;
472     }
473
474     /**
475      * Method called if an exception occurs during the render manager process
476      * As a result of any exception, the user will be removed from the conversation
477      *
478      * @param renderingException that happened
479      */

480     public void renderingException(RenderingException renderingException) {
481         if (log.isDebugEnabled()) {
482             log.debug("Rendering exception called because of " +
483                       renderingException);
484         }
485
486         if (renderer != null) {
487             renderer.remove(this);
488             renderer = null;
489         }
490
491         chatState.removeUserChild(this);
492     }
493 }
494
Popular Tags