001: /*
002: * PollHandler.java
003: *
004: * Brazil project web application Framework,
005: * export version: 1.1
006: * Copyright (c) 2000 Sun Microsystems, Inc.
007: *
008: * Sun Public License Notice
009: *
010: * The contents of this file are subject to the Sun Public License Version
011: * 1.0 (the "License"). You may not use this file except in compliance with
012: * the License. A copy of the License is included as the file "license.terms",
013: * and also available at http://www.sun.com/
014: *
015: * The Original Code is from:
016: * Brazil project web application Framework release 1.1.
017: * The Initial Developer of the Original Code is: suhler.
018: * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
019: * All Rights Reserved.
020: *
021: * Contributor(s): suhler.
022: *
023: * Version: 1.2
024: * Created by suhler on 00/12/13
025: * Last modified by suhler on 00/12/14 17:48:28
026: */
027:
028: package sunlabs.brazil.handler;
029:
030: import java.io.IOException;
031: import java.text.SimpleDateFormat;
032: import java.util.SimpleTimeZone;
033: import java.util.Date;
034: import java.util.Enumeration;
035: import java.util.Locale;
036: import java.util.Properties;
037: import sunlabs.brazil.server.Handler;
038: import sunlabs.brazil.server.Request;
039: import sunlabs.brazil.server.Server;
040: import sunlabs.brazil.util.http.HttpRequest;
041: import sunlabs.brazil.util.regexp.Regexp;
042:
043: /**
044: * Handler for periodically polling another web site, whose
045: * results are (optionally) added to the server's properties.
046: * THis also includes the ability to request URL's on a cron-like schedule.
047: * <p>
048: * The result of fetching the url is expected to be a text document in
049: * java Properties format.
050: * <p>
051: * Properties:
052: * <dl class=props>
053: * <dt>url <dd>The fully qualified URL to fetch periodically.
054: * <dt>interval <dd>The interval (in seconds) to fetch the url. Defaults
055: * to 10 seconds. If <i>match</i> is specified, this is the
056: * interval used to check for a time/date match.
057: * <dt>prepend <dd>The string to prepend to the properties.
058: * If not supplied, no properties are loaded.
059: * <dt>match <dd>If specified, a regular expression that must match
060: * the current time for this URL to run. The format to match is:
061: * "EEE-dd-HH-mm" (eg: Thu-Dec, 14, 14:12 pm).
062: * </dl>
063: *
064: * @author Stephen Uhler
065: * @version %V% PollHandler.java 1.2
066: */
067:
068: public class PollHandler extends Thread implements Handler {
069: String url; // url to fetch
070: int interval; // how often to fetch it (ms)
071: Server server; // our server.
072: String prefix; // our prefix
073: String prepend; // our prefix in the props table
074: Regexp re; // the re to match the date/time expression
075: String then; // Last time we processed this url
076: String match;
077:
078: /**
079: * Set up the initial configuration, and kick off a thread
080: * to periodically fetch the url.
081: */
082:
083: public boolean init(Server server, String prefix) {
084: this .server = server;
085: this .prefix = prefix;
086:
087: interval = 10;
088: prepend = server.props.getProperty(prefix + "prepend");
089: url = server.props.getProperty(prefix + "url");
090: try {
091: String str = server.props.getProperty(prefix + "interval");
092: interval = Integer.decode(str).intValue();
093: } catch (Exception e) {
094: }
095:
096: server.log(Server.LOG_DIAGNOSTIC, prefix, "Polling: " + url
097: + " every " + interval + " seconds");
098:
099: interval *= 1000; // convert to ms
100: if (url == null || interval < 0) {
101: server.log(Server.LOG_WARNING, prefix,
102: "Invalid url or interval");
103: return false;
104: }
105:
106: /*
107: * work on the match stuff
108: */
109:
110: match = server.props.getProperty(prefix + "match");
111: re = null;
112: if (match != null) {
113: try {
114: re = new Regexp(match, true);
115: } catch (Exception e) {
116: server.log(Server.LOG_WARNING, prefix,
117: "Bad expression:" + e);
118: }
119: }
120:
121: Thread poller = (Thread) this ;
122: poller.setDaemon(true);
123: poller.start();
124: return true;
125: }
126:
127: /**
128: * This might allow control over the polling via requests at a later date.
129: * For now, it always returns false.
130: */
131:
132: public boolean respond(Request request) {
133: return false;
134: }
135:
136: /**
137: * The format describing a cron-like date.
138: */
139:
140: private static SimpleDateFormat date;
141: static {
142: date = new SimpleDateFormat("EEE-dd-HH-mm", Locale.US);
143: date.setTimeZone(SimpleTimeZone.getDefault());
144: }
145:
146: /**
147: * Periodically poll the url, and copy the results into the server
148: * properties.
149: */
150:
151: public void
152: run() {
153: Properties props = new Properties();
154: while(true) {
155: try {
156: Thread.sleep(interval);
157: } catch (InterruptedException e) {
158: break;
159: }
160:
161: if (re != null) {
162: String now = date.format(new Date(System.currentTimeMillis()));
163: if (now.equals(then)) {
164: server.log(Server.LOG_DIAGNOSTIC, prefix,
165: "Already polled at: " + now);
166: continue;
167: }
168: if (re.match(now) == null) {
169: server.log(Server.LOG_DIAGNOSTIC, prefix, now +
170: " doesn't match (" + match + ")");
171: continue;
172: }
173: then = now;
174: }
175:
176: server.log(Server.LOG_DIAGNOSTIC, prefix, "Polling: " + url);
177: HttpRequest target = new HttpRequest(url);
178: props.clear();
179: try {
180: props.load(target.getInputStream());
181: } catch (IOException e) {
182: props.put("error", e.getMessage());
183: }
184: target.close();
185: server.log(Server.LOG_DIAGNOSTIC, prefix, " found " + props.size() +
186: " items");
187: props.put("timestamp", "" + System.currentTimeMillis());
188:
189: /*
190: * Copy the properties into the server.
191: */
192:
193: if (prepend != null) {
194: Enumeration enum = props.propertyNames();
195: while(enum.hasMoreElements()) {
196: String key = (String) enum.nextElement();
197: server.props.put(prepend + key, props.getProperty(key));
198: }
199: }
200: }
201: }
202: }
|