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

sunlabs.brazil.properties.SubstPropsHandler Maven / Gradle / Ivy

The newest version!
/*
 * SubstPropsHandler.java
 *
 * Brazil project web application toolkit,
 * export version: 2.3 
 * Copyright (c) 2004-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: suhler.
 * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s): suhler.
 *
 * Version:  1.5
 * Created by suhler on 04/04/27
 * Last modified by suhler on 06/11/13 14:57:53
 *
 * Version Histories:
 *
 * 1.5 06/11/13-14:57:53 (suhler)
 *   Move MatchString from handler -> util
 *
 * 1.4 04/11/30-15:19:44 (suhler)
 *   fixed sccs version string
 *
 * 1.3 04/10/26-11:27:31 (suhler)
 *   add docs
 *
 * 1.2 04/04/28-14:53:05 (suhler)
 *   doc bug fixes
 *
 * 1.2 04/04/27-14:54:59 (Codemgr)
 *   SunPro Code Manager data about conflicts, renames, etc...
 *   Name history : 1 0 sunlabs/SubstPropsHandler.java
 *
 * 1.1 04/04/27-14:54:58 (suhler)
 *   date and time created 04/04/27 14:54:58 by suhler
 *
 */

package sunlabs.brazil.properties;

import java.util.Hashtable;
import java.util.StringTokenizer;
import sunlabs.brazil.util.MatchString;
import sunlabs.brazil.server.Handler;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import sunlabs.brazil.util.regexp.Regexp;
import sunlabs.brazil.util.http.HttpUtil;
import java.io.IOException;

import java.util.Properties;

/**
 * Handler that performs value conversions on ${...} substitutions.
 * For any property whose name matches the supplied regular expression,
 * The source value is "converted" based on a token in the regular expression.
 * 

* This Handler is a generalization of the convert attribute * of the get tag of the SetTemplate. Unlike * the implementation in the SetTemplate that implements a * small, fixed set of conversions of property values in the context of * get, this handler allows plug-able conversion filters, and * performs the conversions any time ${...} substitutions are resolved, not * just in the context of the get tag. *

* This requires the addition of new syntax in ${...} * substitutions to specify the both the * conversion (or filter) to apply, and the value to apply it to. * This new syntax is configurable using the match, * key, and token attributes, but defaults to: * ${filter(value)} where filter represents the conversion * filter, and value represents the property name whose contents * is filtered. *

* Any class that implements the Convert interface can be * loaded and called to perform filtering. Filters that implement all the * options of the <get ... convert=xxx> conversion options * are included. *

* See the examples, below for the details. *

*
match *
A regular expression that matches a property name that is a candidate * for filtering. This expression should have at least 2 sets of ()'s * in order to gather values for "key" and "token" below. The * default value is ^([a-z]+)\([^)]+\)$ *
key *
The regular expression substitution string used to represent the * actual property name to filter. The default is \\2 *
token *
The regular expression substitution string used to represent the * filter name or "token". The default is \\1 *

* Using the defaults for "match", "key", and "token", a property named * "foo" would be represented as ${xxx(foo)} where * "xxx" is the name of the conversion filter. *

tokens *
* A witespace separated list of filter names or "token"s that map the * conversion filters to conversion classes. For each token (e.g. foo), there * should be a property of the form "foo.class" which specifies the name * of the class that implements the filter, (and implements the Convert * interface described below). * Any additional properties (e.g. x, y, z) needed to initialize a filter * should be present in the properties file as "foo.x, foo.y...". *
[token].code *
The name to match the "token" in the property name. The default * is "[token]". *
*

* This class contains sample implementations of the convert * interface. See below for their functions. * * @author Stephen Uhler * @version 1.5 * * @see java.util.Properties */ public class SubstPropsHandler implements Handler { MatchString isMine; // check for matching url Regexp matchRe; // expr that matches a property String keySub; // Substitution string that gets the real key String tokenSub; // Substitution string that matches conversion token Hashtable map = new Hashtable(); // map from token to mapping function static Class[] types = new Class[] {String.class, Properties.class}; public boolean init(Server server, String prefix) { isMine = new MatchString(prefix, server.props); matchRe = new Regexp(server.props.getProperty(prefix + "match", "(^[a-z]+)\\(([^)]+)\\)$")); keySub = server.props.getProperty(prefix + "key", "\\2"); tokenSub=server.props.getProperty(prefix + "token", "\\1"); StringTokenizer st = new StringTokenizer( server.props.getProperty(prefix + "tokens")); // build table of conversions while(st.hasMoreTokens()) { String token = st.nextToken(); String className = server.props.getProperty(token + ".class"); String match=server.props.getProperty(token + ".code", token); String name = prefix; if (className == null) { className = token; // use token as prefix; } else { name = token; } try { Class type = Class.forName(className); Object obj = type.newInstance(); String pre; if (name.endsWith(".")) { pre=name; } else { pre= name + "."; } Object[] args = new Object[] {pre, server.props}; Object result = type.getMethod("init", types).invoke(obj, args); if (Boolean.FALSE.equals(result)) { continue; } if (! (obj instanceof Convert)) { server.log(Server.LOG_WARNING,className, "wrong interface"); continue; } map.put(name, obj); server.log(Server.LOG_DIAGNOSTIC, token, "instantiating class: " + obj); } catch (Exception e) { server.log(Server.LOG_WARNING, prefix, "Oops: " + e); e.printStackTrace(); } } return true; } public boolean respond(Request request) throws IOException { if (isMine.match(request.url)) { SubstProps p = new SubstProps(request); PropertiesList pl = new PropertiesList(p); pl.addBefore(request.serverProps); } return false; } public String toString() { return matchRe + "-" + keySub + "-" + tokenSub + "=" + map; } /** * This class implements a properties object that knows how * to extract the "name" and "filter" from a properly constructed * name, and to invoke the filter on the value of the encoded * name. */ public class SubstProps extends Properties { Request r; public SubstProps(Request r) { super(); this.r = r; } /** * If the key doesn't exist, but the "derived" key and value * do exist, then return the substituted value */ public Object get(Object key) { Object val = super.get(key); String newKey; if (val == null && key instanceof String && null != matchRe.match((String) key)) { newKey = matchRe.sub((String) key, keySub); val = r.props.get(newKey); if (val != null) { String t = matchRe.sub((String) key, tokenSub); val = convert((String)val, t); } } return val; } public String getProperty(String key) { String val = super.getProperty(key); if (val == null && null != matchRe.match(key)) { String newKey = matchRe.sub(key, keySub); val = r.props.getProperty(newKey); if (val != null) { String t = matchRe.sub((String) key, tokenSub); val = convert(val, t); } } return val; } /** * Given a value, compute the converted value. */ String convert(String value, String token) { String result=value; if (token != null) { Convert cnvt = (Convert) map.get(token); if (cnvt != null) { result = cnvt.map(value); } } return result; } } /** * Class that maps strings to strings. */ public interface Convert { /** * This is called once at creation time to provide this * class with configuration information. Any configuration * parameters required in "p" are prefixed with [prefix]. */ public boolean init(String prefix, Properties p); /** * Map the value. */ public String map(String value); } // Sample mapping classes /** * Convert a value to lowercase. */ public static class LowerCase implements Convert { public boolean init(String prefix, Properties p) { return true; } public String map(String value) { return value.toLowerCase(); } } /** * HTML escape a value. */ public static class Html implements Convert { public boolean init(String prefix, Properties p) { return true; } public String map(String value) { return HttpUtil.htmlEncode(value); } } /** * URL encode a String. */ public static class Url implements Convert { public boolean init(String prefix, Properties p) { return true; } public String map(String value) { return HttpUtil.urlEncode(value); } } /** * Do a regexp substitution on a value. * This takes the following initialization parameters: *

*
match *
A Regular expression that matches the string value. *
sub *
The regular expression substitution to perform. * All occurances of "match" are substututed. *
*/ public static class Resub implements Convert { Regexp match = null; String sub = null; public boolean init(String prefix, Properties p) { String matchStr=p.getProperty(prefix + "match"); sub = p.getProperty(prefix + "sub"); match = new Regexp(matchStr); if (match==null || sub == null) { System.out.println("Missing 'match' and 'sub'"); return false; } return true; } public String map(String value) { return match.subAll(value, sub); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy