/* * RePollHandler.java * * Brazil project web application toolkit, * export version: 2.3 * Copyright (c) 2001-2008 Sun Microsystems, Inc. * * Sun Public License Notice * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is included as the file "license.terms", * and also available at http://www.sun.com/ * * The Original Code is from: * Brazil project web application toolkit release 2.3. * The Initial Developer of the Original Code is: suhler. * Portions created by suhler are Copyright (C) Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): suhler. * * Version: 2.3 * Created by suhler on 01/01/31 * Last modified by suhler on 08/12/19 11:14:24 * * Version Histories: * * 2.3 08/12/19-11:14:24 (suhler) * lint * * 2.2 07/01/29-15:36:16 (suhler) * remove unused imports * * 2.1 02/10/01-16:36:33 (suhler) * version change * * 1.13 02/08/01-13:45:02 (suhler) * re-arrange code to make testing easier * * 1.12 02/07/11-15:01:51 (suhler) * use the new getContent() method in httpRequest that does a better job * of charset decoding * * 1.11 02/07/10-11:26:03 (suhler) * add encoding option * * 1.10 01/09/13-09:23:35 (suhler) * remove uneeded import * * 1.9 01/08/14-16:38:19 (suhler) * doc lint * * 1.8 01/08/06-17:46:31 (suhler) * add [prefix].key option to name keys based on sub-matches * * 1.7 01/08/01-17:16:08 (suhler) * - require at least on 'E' flag * - change default falgs to SFE * - lint docs * * 1.6 01/08/01-14:16:03 (suhler) * Completely changed the way properties are extracted. * OLD way: Create a regular expression that turned the content into * a java properties file, then "loaded" it * NEW way Matches and sub-matches are automatically extracted into * properties based on numerical indeces (or names) * * 1.5 01/07/11-16:26:29 (suhler) * doc update * * 1.4 01/06/04-11:05:06 (suhler) * partially implemented new semantics - checked in temporarily * * 1.3 01/03/06-09:06:00 (suhler) * ??? * * 1.2 01/01/31-12:13:37 (suhler) * about to add tcl post-processing option * * 1.2 01/01/31-10:19:38 (Codemgr) * SunPro Code Manager data about conflicts, renames, etc... * Name history : 1 0 handlers/RePollHandler.java * * 1.1 01/01/31-10:19:37 (suhler) * date and time created 01/01/31 10:19:37 by suhler * */ package sunlabs.brazil.handler; import java.io.IOException; import java.util.Properties; import java.util.Hashtable; import java.util.StringTokenizer; import sunlabs.brazil.server.Server; import sunlabs.brazil.server.Request; import sunlabs.brazil.util.regexp.Regexp; import sunlabs.brazil.util.regexp.Regsub; import sunlabs.brazil.util.http.HttpRequest; /** * Do regsub processing on content to extract properties. *

* Properties: *

*
encoding
The character set encoding to use when converting * the request results to a string. Defaults to the * default encoding. *
prepend
The string to prepend to all properties. * Extracted properties will contain the the "re" token * as an additional prefix. *
re
the list of "re" tokens to process in order. * Each "re" token has the following attributes: *
re.exp *
The regular expression to search for. *
re.sub *
The regular expression substitution pattern. If 'E' is specified, * the substitution is done after the extraction. *
re.names *
A white-space delimited set of tokens to use instead of numerical * indices to name the properties. * The first name in the list names the entire match, the remaining * names name the sub-expressions. If there are more properties * extracted than names provided, the "left over" properties will * have numerical indeces. This implies 'E'. *

* If the name "X" is used, no property will be extracted for that * match. *

re.key *
The index of the sub-match (starting at 1) that will be used to * name the row number portion of the property name instead of a * counter. This is useful if one of the sub-matches will be * unique for each matching pattern. This option is ignored if * the "O" flag is specified, as there will be only one match so * no "key" is required. * *
re.flags *
One or more ASCII flags to control how this "re" is processed. * Consists of one or more of The following (defaults to "SFE"):. * Characters not on this list are ignored. * *
*

* First remote content is obtained. Then * each regular expression token is processed in turn for the purpose * of extracting portions of that content into server properties. * [re].sub is used to transform the content before attempting * to extract properties. *

* Content is extracted into the following properties. *

*
prepend.[re].[m].[n] *
The result of the expression associated with token "re". 'n' is * the sub-expression number, and 'm' is the match number, both * starting at '0'. If the 'O' flag is specified, there can * only be one value for 'm', so it is not included (e.g. the * name of the property will be "prepend.[re].[n]). *
prepend.[re].matches *
A list of matches, that may be used as an iterator to foreach. *
prepend.[re].subexpressions *
The number of sub-expressions associated with [re]. *
* * @author Stephen Uhler * @version %V% RePollHandler.java 2.3 */ public class RePollHandler extends PollHandler { Extract[] res = null; String urlPrefix; String encoding; // character coding for extracting results public boolean init(Server server, String prefix) { urlPrefix = server.props.getProperty(prefix + "prefix", "/"); encoding = server.props.getProperty(prefix + "encoding", server.props.getProperty("encoding")); String list = server.props.getProperty(prefix + "re"); if (list == null) { server.log(Server.LOG_WARNING, prefix, "Missing " + prefix + "re"); return super.init(server, prefix); } StringTokenizer st = new StringTokenizer(list); res = new Extract[st.countTokens()]; int i = 0; boolean hasExtract = false; while(st.hasMoreTokens()) { String names[] = null; String name = st.nextToken(); String exp = server.props.getProperty(name + ".exp"); String sub = server.props.getProperty(name + ".sub"); String flags = server.props.getProperty(name + ".flags", "SFE"); if (exp == null) { server.log(Server.LOG_WARNING, prefix, "Can't find " + name + ".exp in properties!!"); return false; } String nameList = server.props.getProperty(name + ".names"); int n = 0; if (nameList != null) { StringTokenizer lt = new StringTokenizer(nameList); names = new String[lt.countTokens()]; while(lt.hasMoreTokens()) { names[n++] = lt.nextToken(); } } int keyIndex = 0; try { String s = server.props.getProperty(name + ".key"); keyIndex = Integer.decode(s).intValue(); } catch (Exception e) {} res[i] = new Extract(name, exp, sub, flags, names, keyIndex); if (res[i].extract()) { hasExtract = true; } i++; } if (!hasExtract) { server.log(Server.LOG_WARNING, prefix, "No properties will be extracted!!"); return false; } return super.init(server, prefix); } /** * Allow The url and post data (if any) to be changed. * A query parameter of the form "url=xxx" replaces the current url. * A query parameter of the form "post=xxx" replaces the post data, if any * was initially defined. */ public boolean respond(Request request) { if (!request.url.startsWith(urlPrefix)) { return false; } Hashtable query = request.getQueryData(); String tmp = (String) query.get("url"); if (tmp != null) { url = tmp; server.log(Server.LOG_DIAGNOSTIC, prefix, "Got new url: " + url); } tmp = (String) query.get("post"); if (post != null && tmp != null) { post = tmp; server.log(Server.LOG_DIAGNOSTIC, prefix, "Got new post data: " + post); } return false; } /** * Fill the properties by extracting fields from the response. This overrides fillProps. */ public void fillProps(Properties props, HttpRequest target) throws IOException { if (res == null) { super.fillProps(props, target); return; } server.log(Server.LOG_INFORMATIONAL, prefix, "polling " + url); processText(props, target.getContent(encoding)); return; } /** * Process the contents as a string through the regular expressions. * This is public, and separate from fillProps to make unit testing easier. */ public void processText(Properties props, String data) { server.log(Server.LOG_DIAGNOSTIC, prefix, "Polled: " + data); String reset = data; boolean previous = true; // result of previous expression for (int i=0; i i) { if (!names[i].equals("X")) { props.put(name + names[i], sub[i]); } } else { props.put(name + i, sub[i]); } } } else if (!single) { Regsub rs = new Regsub(exp, data); while(rs.nextMatch()) { matches++; matchList.append(" " + matches); if (names != null) { if (!names[0].equals("X")) { props.put(name + matches + "." + names[0], rs.matched()); } } else { props.put(name + matches, rs.matched()); } // use sub-match as an index instead of a number String otherKey = null; if (subIndex > 0 && subIndex < subMatches) { otherKey = rs.submatch(subIndex); } if (otherKey == null) { otherKey = "" + matches; } for (int i = 1; i < subMatches; i++) { String key; if (names != null && names.length > i) { if (names[i].equals("X")) { continue; } key = name + otherKey + "." + names[i]; } else { key = name + otherKey + "." + i; } props.put(key, (rs.submatch(i)==null ? nullStr : rs.submatch(i))); } } } ok = (matches > 0); props.put(name + "matches", matchList.toString()); return matches; } /** * true if the previous replace worked */ public boolean replace() { return (sub != null); } public boolean extract() { return extract; } public boolean result() { return ok; } public boolean reset() { return reset; } public boolean fail() { return fail; } public boolean succeed() { return succeed; } public String toString() { return name; } } }