All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sunlabs.brazil.template.RewriteContext Maven / Gradle / Ivy

The newest version!
/*
 * RewriteContext.java
 *
 * Brazil project web application toolkit,
 * export version: 2.3 
 * Copyright (c) 1999-2006 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: cstevens.
 * Portions created by cstevens are Copyright (C) Sun Microsystems, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s): cstevens, drach, guym, suhler.
 *
 * Version:  2.9
 * Created by cstevens on 99/09/29
 * Last modified by suhler on 06/12/18 14:37:27
 *
 * Version Histories:
 *
 * 2.9 06/12/18-14:37:27 (suhler)
 *   add snarfTillClose() to allow grabbing all content inside a tag-pair.
 *   This supports nesting
 *
 * 2.8 06/11/13-11:59:55 (suhler)
 *   add substAttributeValues() convenience method
 *
 * 2.7 06/08/01-14:06:04 (suhler)
 *   added templateFromTag()
 *
 * 2.6 05/06/16-08:05:26 (suhler)
 *   Moved getNamespaceProperties here!
 *
 * 2.5 03/08/01-16:19:12 (suhler)
 *   fixes for javadoc
 *
 * 2.4 03/07/10-09:23:51 (suhler)
 *   Use common "isTrue/isFalse" code in utin/format.
 *
 * 2.3 03/07/09-12:28:03 (suhler)
 *   added "templatePrefix" variable so templates can refer to template
 *   wide prefixes if needed
 *
 * 2.2 03/07/07-14:04:05 (suhler)
 *   add convenience methods for checking for closing tags.  This deals with
 *   tagPrefix's properly
 *
 * 2.1 02/10/01-16:36:49 (suhler)
 *   version change
 *
 * 1.14 01/10/03-13:54:27 (suhler)
 *   addrd "tagsSeen" for diagnostics
 *
 * 1.13 01/09/13-09:23:59 (suhler)
 *   remove uneeded import
 *
 * 1.12 01/08/10-14:56:25 (guym)
 *   Per code review, made Abort, Break, Continue flags an enum, plus fixed a couple of bugs
 *
 * 1.11 01/08/03-20:28:09 (guym)
 *   Added support for , ,  processing
 *
 * 1.10 01/07/16-16:48:14 (suhler)
 *   Added convenience methods
 *
 * 1.9 01/05/02-15:32:24 (drach)
 *   Add template tokens
 *
 * 1.8 00/07/06-15:48:56 (suhler)
 *   doc update
 *
 * 1.7 00/07/05-14:10:21 (cstevens)
 *   Server object is in RewriteContext used by templates, so templates (such as
 *   the TclServerTemplate) can be initialized with the server and prefix, similar
 *   to how Handlers are initialized.
 *
 * 1.6 00/06/29-10:46:06 (suhler)
 *   Added serverProps field (is this a good idea?).
 *
 * 1.5 00/05/31-13:48:03 (suhler)
 *   name change
 *
 * 1.4 00/05/24-11:26:37 (suhler)
 *   add docs
 *
 * 1.3 99/10/28-17:22:50 (cstevens)
 *   ChangedTemplate
 *
 * 1.2 99/10/21-18:13:59 (cstevens)
 *   TemplateHandler now takes a list of Templates, rather than just one.  When
 *   parsing an HTML file, it will now dispatch to the union of all the tag
 *   methods defined in the list of Templates.  In that way, the user can
 *   compose things like the BSLTemplate to iterate over request properties with
 *   the PropsTemplate to substitute in their values.  Otherwise, it would have
 *   required N separate passes (via N separate TemplateHandlers) over the HTML
 *   file, one for each Template and/or level of recursion in the BSLTemplate.
 *
 * 1.2 99/09/29-16:13:31 (Codemgr)
 *   SunPro Code Manager data about conflicts, renames, etc...
 *   Name history : 2 1 handlers/templates/RewriteContext.java
 *   Name history : 1 0 handlers/templates/HtmlRewriter.java
 *
 * 1.1 99/09/29-16:13:30 (cstevens)
 *   date and time created 99/09/29 16:13:30 by cstevens
 *
 */

package sunlabs.brazil.template;

import java.util.Properties;
import java.util.Vector;
import java.util.Enumeration;
import sunlabs.brazil.handler.HtmlRewriter;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import sunlabs.brazil.session.SessionManager;
import sunlabs.brazil.util.Format;

/**
 * A variant containing instance variables that may be referenced by
 * rewriting filters.  Every implementation of the template class
 * may define methods of the form:
 * tag_xxx
 * or
 * tag_slash_xxx
 * which will get called when the corrosponding HTML entity
 * <xxx ...>
 * or
 * </xxx ...>
 * is found in the content being filtered.
 * 

* An instance of this class is passed to each tag * method, permitting introspection of the current filtering context. * * @version %V% RewriteContext.java */ public class RewriteContext extends HtmlRewriter { /** * The server object, as passed to a handler's init method. */ public Server server; // The server, containing properties. /** * The prefix to use for locating keys in the server or request properties * objects. This is a dynamic value that changes during template * processing. Before each template is processed, it is set to the * prefix associated with the template class that the current tag belongs * to. */ public String prefix; /** * This is the prefix defined by the invoker of a set of templates. Its * value corrosponds to the class that invokes a set of templates. */ public String templatePrefix; /** * The Request object, as passed to a handler's respond method. */ public Request request; // The current request /** * A unique session id, if available. */ public String sessionId; // The session ID (if any) /** * Application specific placeholder. */ Object[] args; // app. specific extra stuff TemplateRunner runner; Vector templates; /* Private flags enumeration for RewriteContext state */ /* Note that the BSLTemplate has defined the 0,1,2 bits */ /* for these flags - Hex values 0x1, 0x2, 0x4 */ private int stateFlags; /* Private state variable to track the depth of our recursive descent */ private int nestingLevel; /* Our constructor */ public RewriteContext(Server server, String prefix, Request request, String content, String sessionId, TemplateRunner runner, Vector templates) { super(content); this.server = server; this.prefix = prefix; this.templatePrefix = prefix; this.request = request; this.sessionId = sessionId; this.runner = runner; this.templates = templates; this.args = new Object[] {this}; stateFlags = 0; nestingLevel = 0; } /** * Cause this RewriteContext to abort its processing. */ public void abort() { this.lex.replace(""); setRewriteState(BSLTemplate.ABORT); } /** * Set the given state of this RewriteContext. */ public boolean setRewriteState(int state) { boolean nesting = (nestingLevel >= 1); if (nesting) { stateFlags |= state; } return nesting; } /** * Unset the given state of this RewriteContext. */ public void unsetRewriteState(int state) { stateFlags &= ~state; } /** * Check whether this RewriteContext is in the specified state. */ public boolean checkRewriteState(int state) { return (stateFlags & state) != 0; } /** * Increment the nesting level counter. */ public void incrNestingLevel() { nestingLevel++; } /** * Decrement the nesting level counter. */ public void decrNestingLevel() { if (nestingLevel != 0) { nestingLevel--; } else { System.err.println("Someone tried to decrement the nesting level past zero!"); } } /** * Return the current nesting level counter. */ public int getNestingLevel() { return nestingLevel; } /** * Invoke a template on this token, if any template is interested in this * token. The template may consume more than just this token, if it * wants. */ public void process() { runner.process(this); } /* Convenience methods */ /** * Return the number of HTML tags seen to this point. * */ public int tagsSeen() { return runner.tagsSeen(); } /** * overwrite "get" to automatically do ${...} substitutions * The default is "true". Setting the default to "false" and * recompiling is more backward compatible (but less useful). */ public String get(String name) { return get(name, true); } /** * Get an attribute value, and optionally perform ${...} substitutions. */ public String get(String name, boolean subst) { if (subst) { return Format.subst(request.props, super.get(name)); } else { return(super.get(name)); } } /** * Get a tag attribute, with a default value. * The name is looked-up as an attribute in the current tag. If * it is not found, the configuration property by the same name is used. * If that is not found, dflt is used instead. * * @param name The name of the attribute to look up * @param dflt The default attribute value (may be null) * @return The value of "name" */ public String get(String name, String dflt) { String result = get(name); if (result == null) { result = request.props.getProperty(prefix + name, dflt); } return result; } /** * Determine the value of a boolean attribute in the current tag. * ${...} substitution is performed on the value. * @param name The name of the boolean attribute * @return false if the value is: * null, "", "0", "no", "off", or "false" * true otherwise. * "attribute=" is false, but "attribute" with no * value is true; */ public boolean isTrue(String name) { String value = get(name); if (value==null) { return false; } if (value.length() == 0) { return (getArgs().toLowerCase().indexOf(name + "=") == -1); } value = value.trim().toLowerCase(); if (Format.isFalse(value)) { return false; } else { return true; } } /** * See if the current token is the closing tag for the given string. * Account for tag prefix, if any. * @param tag tag whose match ( e.g. /[prefix]tag is to be found * @return true if the current tag closes "tag" */ public boolean isClosingFor(String tag) { return isClosingFor(tag, true); } /** * See if the current token is the closing tag for the given string. * Account for tag prefix, if any. * @param tag tag whose match ( e.g. /[prefix]tag is to be found * @param close if set, "tag" matches "/[prefix]tag", otherwise * tag matches "[prefix]tag". * @return true if the current tag closes "tag" */ public boolean isClosingFor(String tag, boolean close) { String currentTag = getTag(); if (currentTag == null || (close && !currentTag.startsWith("/")) || !currentTag.endsWith(tag)) { return false; } return currentTag.equals((close ? "/" : "") + getTagPrefix() + tag); } /** * Grab all the markup between the current tag, and the corrosponding * closing tag. Nesting is supported. If there is no markup, or * the current tag is a singleton, the empty string is returned. * The starting and ending tags are not included in the markup. */ public String snarfTillClose() { if (isSingleton()) { return ""; } String match = getTag(); int nestingLevel = 0; StringBuffer sb = new StringBuffer(""); while(nextToken()) { String tag = getTag(); if (tag == null) { sb.append(getToken()); continue; } if (tag.equals(match) && !isSingleton()) { nestingLevel++; } else if (tag.equals("/" + match) && (--nestingLevel < 0)) { nextToken(); break; } sb.append(getToken()); } return sb.toString(); } /** * Add a closing tag to the list of tags that mark un-interpreted text * Deal with the tag prefix, if any */ public void addClosingTag(String tag) { String add = getTagPrefix() + tag; if (lex.getClosingTags().indexOf(add) == -1) { lex.getClosingTags().addElement(add); } } /** * get the tag prefix associated with the current tag. */ String getTagPrefix() { return server.props.getProperty(prefix + TemplateRunner.TAG_PREFIX, server.props.getProperty(templatePrefix + TemplateRunner.TAG_PREFIX, "")); } /** * Get the proper properties table based on the "namespace" * attribute. The namespaces "local" (the default) and "server" * are special. The "sessionTable" cinfiguration * property can be used to override the default session-table, * which defaults to the template handler/filter prefix. */ public Properties getNamespaceProperties() { Properties props; String namespace = get("namespace"); if (namespace==null || namespace.equals("local")) { props = request.props; } else if ("server".equals(namespace)) { props = server.props; } else { String sessionTable = get("sessionTable", templatePrefix); props = (Properties) SessionManager.getSession(namespace, sessionTable, Properties.class); } return props; } /** * Get the template that will process the supplied tag (if any). * This allows template classes to get a handle on the template instances * of other classes running in the same template processing step. If * you need this (and sometimes you do), then there is an architectual * flaw, either in the template system or your classes or both. * * @param tag the name of the html tag that will get processed * @return The template instance, if one exists. */ public Template templateFromTag(String tag) { return runner.templateFromTag(this, tag); } /** * Substitute all attribute values. */ public void substAttributeValues() { Enumeration e = keys(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); put(key, get(key)); // do substitutions } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy