001: /*
002: * SetTemplate.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.9
024: * Created by suhler on 00/10/25
025: * Last modified by suhler on 00/12/12 13:04:59
026: */
027:
028: package sunlabs.brazil.template;
029:
030: import java.io.Serializable;
031: import java.util.Dictionary;
032: import java.util.Enumeration;
033: import sunlabs.brazil.server.Handler;
034: import sunlabs.brazil.server.Request.RechainableProperties;
035: import sunlabs.brazil.server.Request;
036: import sunlabs.brazil.server.Server;
037: import sunlabs.brazil.session.SessionManager;
038: import sunlabs.brazil.util.Format;
039: import sunlabs.brazil.util.Glob;
040:
041: /**
042: * Template (and handler) class for Setting a value into the request props.
043: * This class is used by the TemplateHandler.
044: * <p>
045: * The tag<code><set></code> is processed with the following
046: * attributes:
047: * <dl class=attributes>
048: * <dt>name=<i>value</i>
049: * <dd>The name of the entry to set in the request properties.
050: * <dt>value=<i>value</i>
051: * <dd>The value to set. If no value is provided, any existing value
052: * is removed.
053: * <dt>local
054: * <dd>By default, variables are set (or removed from)
055: * a namespace that is persistent across all requests for the same session.
056: * if <b>local</b> is specified, the values only remain for the
057: * duration of the current request.
058: * </dl>
059: * Request Properties:
060: * <dl class=props>
061: * <dt>sessionTable<dd>The name of the SessionManager table to use for
062: * storing values. Defaults to the handler's prefix.
063: * <dt>debug <dd>If set, the original tag is included in a comment,
064: * otherwise it is removed entirely.
065: * <dt>mustMatch<dd>Set to a glob pattern that all names must match
066: * in order to be set. This may be used to prevent malicious
067: * html pages (what a concept) from changing inappropriate
068: * values.
069: * <dt>querySet<dd>If set, then properties may be set in query
070: * parameters, to the "handler" portion, but only
071: * if they match the glob pattern.
072: * </dl>
073: * <p>
074: * Normally, any persistent properties held by the SetTemplate are
075: * chained onto the request.props when the init method is found. If this
076: * template is installed as an up-stream handler, then the persistent
077: * properties associated with the session are made available at that time.
078: * <p>
079: * When used as a handler, the following property is used:
080: * <dl class=props>
081: * <dt>session=<i>value</i>
082: * <dd>The request property to find the session information in.
083: * Normally this should be the same as the session property used
084: * by the container calling this as a template.
085: * </dl>
086: *
087: * @author Stephen Uhler
088: * @version %V% SetTemplate.java 1.9
089: */
090:
091: public class SetTemplate extends Template implements Serializable,
092: Handler {
093: RechainableProperties props = null;
094: transient boolean debug;
095: String mustMatch;
096: String prefix = null;
097: String session;
098: String sessionTable;
099: String querySet;
100:
101: /**
102: * Chain our private properties into the request chain.
103: */
104:
105: public boolean init(RewriteContext hr) {
106: debug = (hr.request.props.getProperty(hr.prefix + "debug") != null);
107: mustMatch = hr.request.props.getProperty(hr.prefix
108: + "mustMatch");
109: sessionTable = hr.request.props.getProperty(hr.prefix
110: + "sessionTable", hr.prefix);
111: props = (RechainableProperties) SessionManager
112: .getSession(hr.sessionId, sessionTable,
113: RechainableProperties.class);
114: if (prefix == null) {
115: insert(hr.request.props, props, hr.sessionId);
116: }
117: return true;
118: }
119:
120: /**
121: * Set the value of a variable. Allow variable substitutions in the name
122: * and value.
123: */
124:
125: public void tag_set(RewriteContext hr) {
126: if (debug) {
127: hr.append("<!-- " + hr.getBody() + " -->");
128: }
129: hr.killToken();
130:
131: String name = Format.subst(hr.request.props, hr.get("name"));
132: if (name == null) {
133: return;
134: }
135: if (mustMatch != null && !Glob.match(mustMatch, name)) {
136: hr.request.log(Server.LOG_DIAGNOSTIC, hr.prefix, name
137: + " doesn't match " + mustMatch);
138: return;
139: }
140: String value = Format.subst(hr.request.props, hr.get("value"));
141: RechainableProperties p = (hr.get("local") == null) ? props
142: : hr.request.props;
143:
144: if (value != null) {
145: p.put(name, value);
146: hr.request.log(Server.LOG_DIAGNOSTIC, hr.prefix, "putting "
147: + name + "=" + value + " to: " + p);
148: } else {
149: p.remove(name);
150: hr.request.log(Server.LOG_DIAGNOSTIC, hr.prefix,
151: "removing " + name);
152: }
153: }
154:
155: public boolean init(Server server, String prefix) {
156: this .prefix = prefix;
157: querySet = server.props.getProperty(prefix + "querySet");
158: sessionTable = server.props.getProperty(
159: prefix + "sessionTable", prefix);
160: session = server.props.getProperty(prefix + "session",
161: "SessionID");
162: return true;
163: }
164:
165: /**
166: * This is an experiment
167: */
168:
169: public boolean respond(Request request) {
170: String id = request.props.getProperty(session);
171: if (id != null) {
172: props = (RechainableProperties) SessionManager.getSession(
173: id, sessionTable, RechainableProperties.class);
174: insert(request.props, props, id);
175: request.log(Server.LOG_DIAGNOSTIC, prefix, "Chaining: "
176: + props);
177: }
178:
179: /*
180: * Set some properties as part of the request.
181: * Should they be persistent or not?
182: */
183:
184: if (querySet != null) {
185: Dictionary h = request.getQueryData(null);
186: Enumeration keys = h.keys();
187: while (keys.hasMoreElements()) {
188: String key = (String) keys.nextElement();
189: if (Glob.match(querySet, key)) {
190: request.props.put(key, h.get(key));
191: // System.out.println("SET Setting: " + key + " -> " + h.get(key));
192: }
193: }
194: }
195: return false;
196: }
197:
198: /*
199: * XXX temporary bug workaround.
200: * We need to make sure the same table doesn't get chained twice,
201: * or we'll end up with an infinite loop.
202: */
203:
204: static void insert(RechainableProperties root,
205: RechainableProperties add, String token) {
206: if (add == null) {
207: return;
208: }
209: add.put(token, "OK");
210: boolean ok = root.getProperty(token) == null;
211: if (ok) {
212: // System.out.println("CHAINING " + add);
213: add.setDefaults(root.getDefaults());
214: root.setDefaults(add);
215: } else {
216: // System.out.println("Already Chained: " + add);
217: }
218: }
219: }
|