001: /*
002: * TemplateFilter.java
003: *
004: * Brazil project web application Framework,
005: * export version: 1.1
006: * Copyright (c) 1999-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): cstevens, suhler.
022: *
023: * Version: 1.22
024: * Created by suhler on 99/07/29
025: * Last modified by suhler on 00/12/11 13:25:57
026: */
027:
028: package sunlabs.brazil.filter;
029:
030: import sunlabs.brazil.server.Request;
031: import sunlabs.brazil.server.Server;
032: import sunlabs.brazil.util.http.MimeHeaders;
033: import sunlabs.brazil.template.TemplateRunner;
034:
035: import java.util.Properties;
036:
037: /**
038: * The <code>TemplateFilter</code> sends HTML content through an
039: * Html/XML parser to a set of <code>Template</code>s. Each Html/XML tag may
040: * dynamically invoke a Java method present in the <code>Template</code>s.
041: * The dynamically-generated content from evaluating the Html/XML tags is
042: * returned to the caller.
043: * <p>
044: * The following configuration parameters are used to initialize this
045: * <code>Filter</code>.
046: * <dl class=props>
047: * <dt> <code>templates</code>
048: * <dd> A list of <code>Template</code> class names whose methods will be
049: * invoked by the XML tags present in the content.
050: *
051: * <dt> <code>session</code>
052: * <dd> The request property that contains the session ID. If no
053: * "session" property is found with the supplied prefix, then
054: * the global "session" property is used instead. The default
055: * value is "SessionID".
056: * <dt> <code>subtype</code>
057: * <dd> Specify the media subtype for this filter to handler. Defaults
058: * to "html" (as in text/html).
059: *
060: * </dl>
061: * The <code>TemplateHandler</code> class is similar, but not identical to
062: * running a <code>FilterHandler</code> with the <code>FileHandler</code> and
063: * the <code>TemplateFilter</code>. The differences between the two should
064: * be resolved.
065: * <p>
066: * Note: The <code>templates</code> currently accepts only a list of
067: * class names, and not <i>tokens</i> that could be used to represent
068: * class names. This may be changed in the future. Until then, all
069: * template classes share the TemplateHandler's properties prefix.
070: *
071: * @author Stephen Uhler (stephen.uhler@sun.com)
072: * @author Colin Stevens (colin.stevens@sun.com)
073: * @version 1.22, 00/12/11
074: */
075:
076: public class TemplateFilter implements Filter {
077: private static final String TEMPLATES = "templates";
078: private static final String SESSION = "session";
079:
080: Server server;
081: String prefix;
082: String subtype; // media subtype to filter (must be text)
083:
084: String session = "SessionID"; // our session ID property name
085:
086: private TemplateRunner runner; // The template object for our class
087:
088: public boolean init(Server server, String prefix) {
089: Properties props = server.props;
090:
091: this .server = server;
092: this .prefix = prefix;
093:
094: String name = props.getProperty(prefix + TEMPLATES, "");
095: subtype = "text/"
096: + props.getProperty(prefix + "subtype", "html");
097: try {
098: runner = new TemplateRunner(name);
099: } catch (Exception e) {
100: server.log(Server.LOG_ERROR, prefix, "Can't instantiate "
101: + e.getMessage());
102: return false;
103: }
104:
105: session = props.getProperty(prefix + SESSION, session);
106:
107: return true;
108: }
109:
110: /**
111: * No action before request is made
112: */
113:
114: public boolean respond(Request request) {
115: return false;
116: }
117:
118: /**
119: * Filters all HTML files, or files that are likely to be html files,
120: * specifically, those whose "Content-Type" starts with "text/".
121: */
122: public boolean shouldFilter(Request request, MimeHeaders headers) {
123: String type = headers.get("Content-Type");
124: boolean filter = ((type != null) && type.toLowerCase()
125: .startsWith("text/"));
126: request.log(Server.LOG_DIAGNOSTIC, prefix + "type: " + type
127: + " filter?: " + filter);
128: return filter;
129: }
130:
131: /**
132: * Evaluates the content as html/XML tags, if the file is (or has now been
133: * converted to) "text/html".
134: */
135: public byte[] filter(Request request, MimeHeaders headers,
136: byte[] content) {
137: if (headers.get("Content-Type").toLowerCase().startsWith(
138: subtype) == false) {
139: request.log(Server.LOG_DIAGNOSTIC, prefix + " Not "
140: + subtype + ", skipping");
141: return content;
142: }
143:
144: /*
145: * Get the cookie out of the request object (presumably from the
146: * sessionhandler). If not there, don't use cookies.
147: */
148:
149: String sessionId = request.props.getProperty(session);
150: if (sessionId == null) {
151: sessionId = "noCookie";
152: request.log(Server.LOG_WARNING,
153: "template not using cookies");
154: }
155:
156: /*
157: * Process the content as a template. If there is an error,
158: * leave the content unchanged.
159: */
160:
161: String result = runner.process(server, prefix, request,
162: new String(content), sessionId);
163: if (result != null) {
164: return result.getBytes();
165: } else {
166: request.log(Server.LOG_INFORMATIONAL, "template Error: "
167: + runner.getError());
168: return content;
169: }
170: }
171: }
|