001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.util.functions;
011:
012: import java.util.*;
013: import java.util.regex.*;
014: import javax.servlet.http.HttpServletRequest;
015: import java.lang.reflect.Method;
016: import org.mmbase.bridge.Node;
017: import org.mmbase.util.Casting;
018: import org.mmbase.util.logging.Logger;
019: import org.mmbase.util.logging.Logging;
020:
021: /**
022: * This Function provider creates function objects , which can create a String function based on a
023: * pattern. Several kind of patterns are recognized. {PARAM.abc} creates a parameter 'abc' and puts the
024: * value of it on that place in the result. {NODE.title}, puts the title field of the node on which
025: * the function was applied on that place, and {REQUEST.getContextPath} applies that method to the
026: * request parameter (and the result is added). {INITPARAM.xyz} access the servletcontext init parameters xyz.
027: *
028: * It is also possible to use request parameters and attributes with {REQUESTPARAM.xxx} and {REQUESTATTRIBUTE.yyy}.
029: *
030: * The functions which are created have silly names like string0, string1 etc, so you want to wrap
031: * them in a function with a reasonable name (this is done when specifying this thing in the builder
032: * xml).
033: *
034: * @author Michiel Meeuwissen
035: * @version $Id: PatternNodeFunctionProvider.java,v 1.15 2007/07/27 14:07:07 michiel Exp $
036: * @since MMBase-1.8
037: */
038: public class PatternNodeFunctionProvider extends FunctionProvider {
039:
040: private static final Logger log = Logging
041: .getLoggerInstance(PatternNodeFunctionProvider.class);
042: private static final PatternNodeFunctionProvider instance = new PatternNodeFunctionProvider();
043:
044: public PatternNodeFunctionProvider() {
045: }
046:
047: public static PatternNodeFunctionProvider getInstance() {
048: return instance;
049: }
050:
051: public Function<String> getFunction(String name) {
052: Function func = functions.get(name);
053: if (func == null) {
054: func = new PatternNodeFunction(name);
055: functions.put(name, func);
056: }
057: return func;
058: }
059:
060: private static final Pattern requestPattern = Pattern
061: .compile("\\{REQUEST\\.(.+?)\\}");
062: private static final Pattern requestParamPattern = Pattern
063: .compile("\\{REQUESTPARAM\\.(.+?)\\}");
064: private static final Pattern requestAttributePattern = Pattern
065: .compile("\\{REQUESTATTRIBUTE\\.(.+?)\\}");
066:
067: public static Map<String, Method> getRequestMethods(String template) {
068: // could use cache here to avoid the reflection overhead
069: Matcher matcher = requestPattern.matcher(template);
070: if (matcher.find()) {
071: matcher.reset();
072: Map<String, Method> requestMethods = new HashMap<String, Method>();
073: while (matcher.find()) {
074: try {
075: requestMethods.put(matcher.group(1),
076: HttpServletRequest.class.getMethod(matcher
077: .group(1)));
078: } catch (NoSuchMethodException nsme) {
079: log.error(nsme.getMessage(), nsme);
080: }
081: }
082: return requestMethods;
083: } else {
084: return null;
085: }
086: }
087:
088: /**
089: * @param sb StringBuffer (not a StringBuilder, because there is no appendTail(StringBuilder)...)
090: * @since MMBase-1.9
091: */
092: public static void handleRequest(StringBuffer sb,
093: Parameters parameters, Map<String, Method> requestMethods) {
094: {
095: Matcher request = requestPattern.matcher(sb.toString());
096: if (request.find()) {
097: request.reset();
098: HttpServletRequest req = parameters
099: .get(Parameter.REQUEST);
100: sb.setLength(0);
101: while (request.find()) {
102: if (request.group(1).equals("getContextPath")) {
103: String r = req == null ? org.mmbase.module.core.MMBaseContext
104: .getHtmlRootUrlPath()
105: : req.getContextPath() + '/';
106: request.appendReplacement(sb, r.substring(0, r
107: .length() - 1));
108: continue;
109: }
110: if (req == null) {
111: log
112: .error("Did't find the request among the parameters");
113: continue;
114: }
115: try {
116: Method m = requestMethods.get(request.group(1));
117: if (m == null) {
118: log.error("Didn't find the method "
119: + request.group(1)
120: + " on request object");
121: continue;
122: }
123: request.appendReplacement(sb, ""
124: + m.invoke(req, new Object[] {}));
125: } catch (IllegalAccessException iae) {
126: log.error(iae.getMessage(), iae);
127: } catch (java.lang.reflect.InvocationTargetException ite) {
128: log.error(ite.getMessage(), ite);
129: }
130: }
131: request.appendTail(sb);
132: }
133: }
134: {
135: Matcher requestParam = requestParamPattern.matcher(sb
136: .toString());
137: if (requestParam.find()) {
138: HttpServletRequest req = parameters
139: .get(Parameter.REQUEST);
140: if (req == null) {
141: log
142: .error("Did't find the request among the parameters");
143: } else {
144: requestParam.reset();
145: sb.setLength(0);
146: while (requestParam.find()) {
147: String paramName = requestParam.group(1);
148: String value = req.getParameter(paramName);
149: if (value == null)
150: value = "";
151: requestParam.appendReplacement(sb, value);
152: }
153: requestParam.appendTail(sb);
154: }
155: }
156: }
157: {
158: Matcher requestAttribute = requestAttributePattern
159: .matcher(sb.toString());
160: if (requestAttribute.find()) {
161: HttpServletRequest req = parameters
162: .get(Parameter.REQUEST);
163: if (req == null) {
164: log
165: .error("Did't find the request among the parameters");
166: } else {
167: requestAttribute.reset();
168: sb.setLength(0);
169: while (requestAttribute.find()) {
170: String paramName = requestAttribute.group(1);
171: String value = Casting.toString(req
172: .getAttribute(paramName));
173: requestAttribute.appendReplacement(sb, value);
174: }
175: requestAttribute.appendTail(sb);
176: }
177: }
178: }
179: }
180:
181: private static final Pattern fieldsPattern = Pattern
182: .compile("\\{NODE\\.(.+?)\\}");
183: private static final Pattern paramPattern = Pattern
184: .compile("\\{PARAM\\.(.+?)\\}");
185: private static final Pattern initParamPattern = Pattern
186: .compile("\\{INITPARAM\\.(.+?)\\}");
187:
188: private static int counter = 0;
189:
190: protected static class PatternNodeFunction extends
191: NodeFunction<String> {
192:
193: final String template;
194: final Map<String, Method> requestMethods;
195:
196: PatternNodeFunction(String template) {
197: super ("string" + (counter++), getParameterDef(template),
198: ReturnType.STRING);
199: this .template = template;
200: this .requestMethods = getRequestMethods(template);
201:
202: }
203:
204: protected static Parameter[] getParameterDef(String template) {
205: List<Parameter> params = new ArrayList<Parameter>();
206: if (requestPattern.matcher(template).find()
207: || requestParamPattern.matcher(template).find()
208: || requestAttributePattern.matcher(template).find()) {
209: params.add(Parameter.REQUEST);
210: }
211: Matcher args = paramPattern.matcher(template);
212: while (args.find()) {
213: params.add(new Parameter(args.group(1), String.class,
214: ""));
215: }
216: return params.toArray(new Parameter[] {});
217: }
218:
219: protected String getFunctionValue(final Node node,
220: final Parameters parameters) {
221: StringBuffer sb = new StringBuffer(); // those guys from Sun forgot to supply Matcher#appendTail(StringBuilder)
222: {
223: Matcher fields = fieldsPattern.matcher(template);
224: while (fields.find()) {
225: fields.appendReplacement(sb, node
226: .getStringValue(fields.group(1)));
227: }
228: fields.appendTail(sb);
229: }
230: handleRequest(sb, parameters, requestMethods);
231: {
232: Matcher params = paramPattern.matcher(sb.toString());
233: if (params.find()) {
234: params.reset();
235: sb.setLength(0);
236: while (params.find()) {
237: params.appendReplacement(sb,
238: (String) parameters
239: .get(params.group(1)));
240: }
241: params.appendTail(sb);
242: }
243: }
244: {
245:
246: Matcher initParams = initParamPattern.matcher(sb
247: .toString());
248: if (initParams.find()) {
249: initParams.reset();
250: sb.setLength(0);
251: while (initParams.find()) {
252: String s = org.mmbase.module.core.MMBaseContext
253: .getServletContext().getInitParameter(
254: initParams.group(1));
255: if (s == null)
256: s = "";
257: initParams.appendReplacement(sb, s);
258: }
259: initParams.appendTail(sb);
260: }
261: }
262: return sb.toString();
263:
264: }
265:
266: }
267: }
|