001: /*
002: * Andy John
003: * 2/99
004: * Chat room
005: * andy@enhydra.org
006: * www.enhydra.org
007: *
008: * Chat - A simple chat room Enhydra application.
009: *
010: * The purpose of this program is to demonstrate ways to use the Enhydra
011: * application framework. Jolt is used for two of the dynamic HTML
012: * pages. One of the pages is generated by a presentation object written
013: * by hand.
014: *
015: * This application uses what an algorithm I call "on hold push", because
016: * it gives you the effect of "push technology", but only uses standard
017: * HTTP. You instantly see when other people send in a message. But it
018: * will work through proxies and firewalls. It is even applicable to
019: * applets, which have additional security restrictions (the stand alone
020: * debugger uses this algorithm to show the requests made to the
021: * servlet that is being debugged). See the Discussion object for a
022: * description of on hold push.
023: *
024: * www.enhydra.org
025: */
026:
027: package chat;
028:
029: import com.lutris.appserver.server.*;
030: import com.lutris.appserver.server.httpPresentation.*;
031: import com.lutris.appserver.server.session.*;
032: import com.lutris.util.*;
033:
034: import chat.spec.*;
035:
036: /**
037: * The application object.
038: * Reads all the settings from the config file.
039: */
040: public class ChatApplication extends StandardApplication {
041:
042: private String roomName = "Chat Room";
043: private String bgColor = "";
044: private String clearCommand = "";
045:
046: /**
047: * Read all the chat room settings at startup time. Some of the
048: * settings are saved, and the other classes refer to this class when
049: * they need the values. Some of the settings are only used once to
050: * initialize parts of the program.
051: */
052: public void startup(Config appConfig) throws ApplicationException {
053: super .startup(appConfig); // Be sure to call this!
054: /*
055: * Get the title of this chat room from the config file.
056: */
057: try {
058: roomName = appConfig.getString("RoomName", "Chat Room");
059: } catch (ConfigException e) {
060: throw new ApplicationException(
061: "Bogus RoomName in config file.", e);
062: }
063: /*
064: * How long should messages be kept? Get from config file.
065: */
066: int messageLifetimeSecs;
067: try {
068: messageLifetimeSecs = appConfig.getInt(
069: "MessageLifetimeSecs", 300);
070: } catch (ConfigException e) {
071: throw new ApplicationException(
072: "Bogus MessageLifetimeSecs in config file.", e);
073: }
074: /*
075: * How often to delete messages that are too old?
076: */
077: int harvestIntervalSecs;
078: try {
079: harvestIntervalSecs = appConfig.getInt(
080: "HarvestIntervalSecs", 55);
081: } catch (ConfigException e) {
082: throw new ApplicationException(
083: "Bogus HarvestIntervalSecs in config file.", e);
084: }
085: /*
086: * Get the max number of messages allowed (if any) from the config
087: * file. You don't know how many hits you will get. If you allow
088: * data structures to grow without limit, your application may
089: * use up all the memory and kill the virtual machine.
090: */
091: int maxQueueSize;
092: try {
093: maxQueueSize = appConfig.getInt("MaxQueueSize", 200);
094: } catch (ConfigException e) {
095: throw new ApplicationException(
096: "Bogus MaxQueueSize in config file.", e);
097: }
098: /*
099: * Get the background color string (if any) from the config file.
100: */
101: try {
102: bgColor = appConfig.getString("BackgroundColor", "#99CCFF");
103: } catch (ConfigException e) {
104: throw new ApplicationException(
105: "Bogus BackgroundColor in config file.", e);
106: }
107: /*
108: * Get the clear command (if any) from the config file.
109: */
110: try {
111: clearCommand = appConfig.getString("ResetCommand", "");
112: } catch (ConfigException e) {
113: throw new ApplicationException(
114: "Bogus ResetCommand in config file.", e);
115: }
116: /*
117: * Configure the DiscussionImpl object.
118: * Maybe start the message deleting thread.
119: */
120:
121: DiscussionManager discussionManager = DiscussionManagerFactory
122: .getDiscussionManager("chat.business.DiscussionManagerImpl");
123:
124: /*
125: * Catch Null pointer exception ( we canot make a instances of classes from business layer when we run chat_pres )
126: * We need to allow chat_pres to be functional
127: */
128: try {
129: discussionManager.setMaxQueueSize(maxQueueSize);
130:
131: if (harvestIntervalSecs < 1)
132: harvestIntervalSecs = 1;
133: if (messageLifetimeSecs > 0)
134:
135: discussionManager.startHarvester(messageLifetimeSecs,
136: harvestIntervalSecs);
137:
138: } catch (NullPointerException e) {
139: }
140:
141: }
142:
143: public boolean requestPreprocessor(HttpPresentationComms comms)
144: throws Exception {
145: return super .requestPreprocessor(comms);
146: }
147:
148: public void shutdown() {
149: DiscussionManager discussionManager = DiscussionManagerFactory
150: .getDiscussionManager("chat.business.DiscussionManagerImpl");
151: try {
152: discussionManager.stopHarvester();
153: } catch (NullPointerException e) {
154: }
155: }
156:
157: /**
158: * The title of this chat room.
159: */
160: public String getRoomName() {
161: return roomName;
162: }
163:
164: /**
165: * What color should the pages be? This is used by both the entry frame
166: * and the contents frame.
167: */
168: public String getBgColor() {
169: return bgColor;
170: }
171:
172: /**
173: * What's the clear command? This will be "" if there is no command.
174: * If this string is sent in (in a message), then delete all the
175: * messages currently in the queue.
176: */
177: public String getClearCommand() {
178: return clearCommand;
179: }
180:
181: /**
182: * This is only called if this application is being run in the
183: * Enhydra Multiserver.
184: * Displays usage stats that an administrator would care about.
185: * The number of listeners is the number of requets blocked
186: * on a read, waiting for messages to appear or be deleted (often
187: * web browsers do "keep alive" behind the scenes, even if the users
188: * hit "stop", this might not go to zero immediatly).
189: *
190: * @return HTML that is displayed in the status page of the Multiserver.
191: */
192: public String toHtml() {
193: String response;
194:
195: DiscussionManager discussionManager = DiscussionManagerFactory
196: .getDiscussionManager("chat.business.DiscussionManagerImpl");
197: int n = discussionManager.getNumWaiting();
198:
199: if (n == 1)
200: response = "There is 1 person listening.";
201: else
202: response = "There are " + n + " people listening.";
203:
204: long l = discussionManager.getTotalReceived();
205:
206: if (l == 1)
207: response += "<br>A total of 1 message has been received so far.";
208: else
209: response += "<br>A total of " + l
210: + " messages have been received.";
211:
212: l = discussionManager.getCurrentSize();
213: if (l == 1)
214: response += "<br>There is currently 1 message.";
215: else
216: response += "<br>There are currently " + l + " messages.";
217: return response;
218: }
219:
220: }
|