001: //** Copyright Statement ***************************************************
002: //The Salmon Open Framework for Internet Applications (SOFIA)
003: // Copyright (C) 1999 - 2002, Salmon LLC
004: //
005: // This program is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU General Public License version 2
007: // as published by the Free Software Foundation;
008: //
009: // This program is distributed in the hope that it will be useful,
010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: // GNU General Public License for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // along with this program; if not, write to the Free Software
016: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: //
018: // For more information please visit http://www.salmonllc.com
019: //** End Copyright Statement ***************************************************
020: package com.salmonllc.servlets;
021:
022: /////////////////////////
023: //$Archive: /SOFIA/SourceCode/com/salmonllc/servlets/Scheduler.java $
024: //$Author: Dan $
025: //$Revision: 10 $
026: //$Modtime: 11/09/04 9:38a $
027: /////////////////////////
028:
029: import java.io.IOException;
030: import java.io.PrintWriter;
031: import java.util.Vector;
032:
033: import javax.servlet.ServletConfig;
034: import javax.servlet.ServletContext;
035: import javax.servlet.ServletException;
036: import javax.servlet.http.*;
037:
038: import com.salmonllc.jsp.JspServlet;
039: import com.salmonllc.properties.Props;
040: import com.salmonllc.scheduler.*;
041: import com.salmonllc.util.*;
042:
043: /**
044: * This servlet is the controller for all the scheduled object in the framework.
045: * <BR>
046: * Each scheduled object must implement the com.salmonllc.ScheduledObject
047: * interface and must be listed in the properties file. When the scheule
048: * interval is reached a new instance of the object will be created and the
049: * schedule reached event will be executed.
050: */
051:
052: public class Scheduler extends HttpServlet implements Runnable {
053: private Vector _list = new Vector();
054: private long _lastReload = -1;
055: private Thread _exeLoop = null;
056: private boolean _threadRunning = false;
057: private boolean _loaded = false;
058:
059: //every half hour go through the open database connections and remove any
060: // that are idle
061: FourObjectContainer _poolCleaner = new FourObjectContainer(
062: new ConnectionPoolCleaner(), new Integer(30), null,
063: new Long(-1));
064:
065: //every half hour go through the objectstore cache and remove old ones
066: FourObjectContainer _cacheCleaner = new FourObjectContainer(
067: new CacheCleaner(), new Integer(30), null, new Long(-1));
068:
069: /**
070: * This method handles get events from the browser.
071: */
072: public void doGet(HttpServletRequest req, HttpServletResponse res)
073: throws ServletException, IOException {
074: JspServlet.setUpApplicationContext(getServletContext(), req);
075: res.setContentType("text/html");
076: res.setHeader("Pragma", "no-cache");
077: res.setDateHeader("Expires", 0);
078: res.setHeader("Cache-Control", "no-cache");
079: res.setStatus(HttpServletResponse.SC_OK);
080:
081: String[] path = req.getParameterValues("ret");
082: if (path == null)
083: generateHtml(res.getWriter());
084: else {
085: String retPath = path[0];
086: if (retPath == null)
087: retPath = "";
088: else if (retPath.equals("null"))
089: retPath = "";
090: res.sendRedirect(URLGenerator.generateServerURL(req) + "/"
091: + URLGenerator.generateServletBaseURL(req)
092: + "/com.salmonllc.servlets.AppServer" + retPath);
093: }
094:
095: }
096:
097: /**
098: * This method handles post events from the browser.
099: */
100: public void doPost(HttpServletRequest req, HttpServletResponse res)
101: throws ServletException, IOException {
102: JspServlet.setUpApplicationContext(getServletContext(), req);
103: res.setContentType("text/html");
104: res.setHeader("Pragma", "no-cache");
105: res.setDateHeader("Expires", 0);
106: res.setHeader("Cache-Control", "no-cache");
107:
108: res.setStatus(HttpServletResponse.SC_OK);
109:
110: String parm[] = req.getParameterValues("START");
111: if (parm != null)
112: startThread();
113: else {
114: parm = req.getParameterValues("STOP");
115: if (parm != null)
116: stopThread();
117: else {
118: parm = req.getParameterValues("RELOAD");
119: reloadInfo(true);
120: }
121: }
122:
123: generateHtml(res.getWriter());
124: }
125:
126: private void executeEvents() {
127: for (int i = 0; i < _list.size(); i++) {
128: FourObjectContainer evt = (FourObjectContainer) _list
129: .elementAt(i);
130: if (evt != null) {
131: Long l = (Long) evt.getObject4();
132: boolean execute = false;
133: if (l.longValue() == -1)
134: execute = true;
135: else {
136: Integer interval = (Integer) evt.getObject2();
137: long nextExeTime = l.longValue()
138: + (interval.intValue() * 60000);
139: long time = System.currentTimeMillis();
140: if (time > nextExeTime) {
141: execute = true;
142: evt.setObject4(new Long(time));
143: }
144: }
145:
146: if (!execute)
147: continue;
148:
149: Object obj = evt.getObject1();
150:
151: String app = "";
152: if (ApplicationContext.getContext() != null)
153: app = " application:"
154: + ApplicationContext.getContext()
155: .getAppID();
156:
157: try {
158: evt
159: .setObject4(new Long(System
160: .currentTimeMillis()));
161: if (obj instanceof String) {
162: Class c = Class.forName((String) obj, true,
163: Thread.currentThread()
164: .getContextClassLoader());
165: Object o = c.newInstance();
166: ScheduledObject so = (ScheduledObject) o;
167: MessageLog.writeInfoMessage(
168: "scheduleReached() for: "
169: + so.toString() + app, this );
170: so.scheduleReached(new ScheduleReachedEvent(
171: (String) evt.getObject3()));
172: } else if (obj instanceof ScheduledObject) {
173: ScheduledObject so = (ScheduledObject) obj;
174: MessageLog.writeInfoMessage(
175: "scheduleReached() for: "
176: + so.toString() + app, this );
177: so.scheduleReached(new ScheduleReachedEvent(
178: (String) evt.getObject3()));
179: }
180: } catch (Exception e) {
181: MessageLog.writeErrorMessage(
182: "executeEvent(), creating class", e, this );
183: }
184:
185: }
186:
187: }
188:
189: }
190:
191: private void generateHtml(PrintWriter p) {
192: Props pr = Props.getSystemProps();
193: if (!pr.getBooleanProperty(Props.SYS_INFO_SERVLETS, true))
194: return;
195:
196: p.println("<HTML><HEAD></HEAD>");
197:
198: String bodyTag = "<BODY";
199: if (pr.getProperty(Props.PAGE_BACKGROUND_COLOR) != null)
200: bodyTag += " BGCOLOR=\""
201: + pr.getProperty(Props.PAGE_BACKGROUND_COLOR)
202: + "\"";
203:
204: if (pr.getProperty(Props.PAGE_BACKGROUND) != null) {
205: String bg = pr.getProperty(Props.PAGE_BACKGROUND);
206: if (bg.startsWith("../../"))
207: bg = bg.substring(6);
208: bodyTag += " BACKGROUND=\"" + bg + "\"";
209: }
210: bodyTag += ">";
211: p.println(bodyTag);
212:
213: String headingFontStart = pr
214: .getProperty(Props.FONT_PAGE_HEADING + Props.TAG_START);
215: String headingFontEnd = pr.getProperty(Props.FONT_PAGE_HEADING
216: + Props.TAG_END);
217:
218: String defaultFontStart = pr.getProperty(Props.FONT_DEFAULT
219: + Props.TAG_START);
220: String defaultFontEnd = pr.getProperty(Props.FONT_DEFAULT
221: + Props.TAG_END);
222:
223: p.println(headingFontStart + "com.salmonllc.servlets.Scheduler"
224: + headingFontEnd + "<BR>");
225:
226: p.println("<BR>");
227: p.println(defaultFontStart + "Status: "
228: + (_threadRunning ? "Running" : "Stopped")
229: + defaultFontEnd + "<BR>");
230: p.println(defaultFontStart + "Objects Scheduled: "
231: + _list.size() + "<BR>");
232: for (int i = 0; i < _list.size(); i++) {
233: p.print(" ");
234: p.print(((FourObjectContainer) _list.elementAt(i))
235: .getObject1());
236: p.print("<BR>");
237:
238: }
239: p.println(defaultFontEnd);
240: p.println("<BR>");
241:
242: p.println("<FORM NAME=\"PageForm\" METHOD=\"POST\">");
243: if (_threadRunning)
244: p
245: .println("<INPUT TYPE=\"SUBMIT\" NAME=\"STOP\" VALUE=\"Stop the com.salmonllc.servlets.Scheduler\">");
246: else
247: p
248: .println("<INPUT TYPE=\"SUBMIT\" NAME=\"START\" VALUE=\"Start the com.salmonllc.servlets.Scheduler\">");
249:
250: p
251: .write("<INPUT TYPE=\"SUBMIT\" NAME=\"RELOAD\" VALUE=\"Reload Information\">");
252: p.write("</FORM>");
253:
254: p.write("</BODY></HTML>");
255: }
256:
257: /**
258: * This method initializes the servlet.
259: */
260: public void init(ServletConfig config) throws ServletException {
261: super .init(config);
262: ServletContext cont = config.getServletContext();
263: JspServlet.setUpApplicationContext(cont);
264: if (Props.isPropsPathShared() && _loaded)
265: return;
266:
267: reloadInfo(true);
268: if (_list.size() > 0)
269: startThread();
270: }
271:
272: /**
273: * This method is called when the servlet is destoryed
274: */
275:
276: public void destroy() {
277: stopThread();
278: MessageLog.stopThreads();
279: super .destroy();
280: }
281:
282: private void reloadInfo(boolean force) {
283: long time = Props.getSystemPropsLastModified();
284:
285: if (!force) {
286: if (time == _lastReload)
287: return;
288: }
289:
290: _loaded = true;
291: _lastReload = time;
292: _list.removeAllElements();
293:
294: Props p = Props.getSystemProps();
295: if (p == null) {
296: _lastReload = -1;
297: return;
298: }
299:
300: int i = 1;
301: int maxScheduledObjects = p
302: .getIntProperty(Props.SYS_SCHEDULER_MAX_OBJECTS);
303:
304: if (maxScheduledObjects <= 0) {
305: maxScheduledObjects = 20;
306: }
307:
308: while (i < maxScheduledObjects) {
309: String object = p.getProperty(Props.SYS_SCHEDULE_OBJECT
310: + "." + i);
311: if (object == null) {
312: i++;
313: continue;
314: }
315:
316: int interval = p.getIntProperty(Props.SYS_SCHEDULE_INTERVAL
317: + "." + i);
318: String application = p
319: .getProperty(Props.SYS_SCHEDULE_APPLICATION + "."
320: + i);
321:
322: FourObjectContainer f = new FourObjectContainer(object,
323: new Integer(interval), application, new Long(-1));
324: _list.addElement(f);
325:
326: i++;
327: }
328:
329: _list.addElement(_poolCleaner);
330: _list.addElement(_cacheCleaner);
331:
332: }
333:
334: public void run() {
335: while (_threadRunning) {
336: reloadInfo(false);
337: if (_threadRunning)
338: executeEvents();
339:
340: try {
341: Thread.sleep(10000);
342: } catch (Exception e) {
343: }
344: }
345: }
346:
347: private void startThread() {
348: if (_threadRunning)
349: return;
350:
351: if (_list.size() == 0)
352: return;
353:
354: _threadRunning = true;
355: _exeLoop = ApplicationContext
356: .createThreadWithContextClone(this );
357: _exeLoop.start();
358: }
359:
360: private void stopThread() {
361: if (!_threadRunning)
362: return;
363:
364: _threadRunning = false;
365: }
366: }
|