001: /*
002: * $Id: FreeMarkerWorker.java,v 1.9 2004/01/13 06:16:30 byersa Exp $
003: *
004: * Copyright (c) 2001-2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.content.webapp.ftl;
026:
027: import java.io.IOException;
028: import java.io.Reader;
029: import java.io.StringReader;
030: import java.io.StringWriter;
031: import java.io.Writer;
032: import java.util.ArrayList;
033: import java.util.HashMap;
034: import java.util.Iterator;
035: import java.util.List;
036: import java.util.Map;
037: import java.util.Set;
038: import javax.servlet.http.HttpServletRequest;
039: import javax.servlet.ServletContext;
040:
041: import org.ofbiz.base.util.Debug;
042: import org.ofbiz.base.util.StringUtil;
043: import org.ofbiz.base.util.UtilMisc;
044: import org.ofbiz.base.util.UtilValidate;
045: import org.ofbiz.entity.GenericDelegator;
046: import org.ofbiz.entity.GenericEntityException;
047: import org.ofbiz.entity.GenericValue;
048: import org.ofbiz.entity.GenericPK;
049:
050: import freemarker.ext.beans.BeanModel;
051: import freemarker.ext.beans.BeansWrapper;
052: import freemarker.template.Configuration;
053: import freemarker.template.Environment;
054: import freemarker.template.SimpleHash;
055: import freemarker.template.SimpleScalar;
056: import freemarker.template.Template;
057: import freemarker.template.TemplateException;
058: import freemarker.template.TemplateHashModel;
059: import freemarker.template.TemplateModelException;
060:
061: /**
062: * FreemarkerViewHandler - Freemarker Template Engine Util
063: *
064: * @author <a href="mailto:byersa@automationgroups.com">Al Byers</a>
065: * @version $Revision: 1.9 $
066: * @since 3.0
067: */
068: public class FreeMarkerWorker {
069:
070: public static final String module = FreeMarkerWorker.class
071: .getName();
072:
073: public static OfbizUrlTransform ofbizUrl = new OfbizUrlTransform();
074: public static OfbizContentTransform ofbizContentUrl = new OfbizContentTransform();
075: public static OfbizCurrencyTransform ofbizCurrency = new OfbizCurrencyTransform();
076: public static SetRequestAttributeMethod setRequestAttribute = new SetRequestAttributeMethod();
077: public static EditRenderSubContentTransform editRenderSubContent = new EditRenderSubContentTransform();
078: public static RenderSubContentTransform renderSubContent = new RenderSubContentTransform();
079: public static RenderWrappedTextTransform renderWrappedText = new RenderWrappedTextTransform();
080: public static LoopSubContentTransform loopSubContent = new LoopSubContentTransform();
081: public static TraverseSubContentTransform traverseSubContent = new TraverseSubContentTransform();
082:
083: public static EditRenderSubContentCacheTransform editRenderSubContentCache = new EditRenderSubContentCacheTransform();
084: public static RenderSubContentCacheTransform renderSubContentCache = new RenderSubContentCacheTransform();
085: public static LoopSubContentCacheTransform loopSubContentCache = new LoopSubContentCacheTransform();
086: public static TraverseSubContentCacheTransform traverseSubContentCache = new TraverseSubContentCacheTransform();
087: public static CheckPermissionTransform checkPermission = new CheckPermissionTransform();
088: public static InjectNodeTrailCsvTransform injectNodeTrailCsv = new InjectNodeTrailCsvTransform();
089:
090: public static void addAllOfbizTransforms(Map context) {
091: BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
092: TemplateHashModel staticModels = wrapper.getStaticModels();
093: context.put("Static", staticModels);
094:
095: context.put("ofbizUrl", ofbizUrl);
096: context.put("ofbizContentUrl", ofbizContentUrl);
097: context.put("ofbizCurrency", ofbizCurrency);
098: context.put("setRequestAttribute", setRequestAttribute);
099: context.put("editRenderSubContent", editRenderSubContent);
100: context.put("renderSubContent", renderSubContent);
101: context.put("loopSubContent", loopSubContent);
102: context.put("traverseSubContent", traverseSubContent);
103: context.put("renderWrappedText", renderWrappedText);
104: context.put("editRenderSubContentCache",
105: editRenderSubContentCache);
106: context.put("renderSubContentCache", renderSubContentCache);
107: context.put("loopSubContentCache", loopSubContentCache);
108: context.put("traverseSubContentCache", traverseSubContentCache);
109: context.put("checkPermission", checkPermission);
110: context.put("injectNodeTrailCsv", injectNodeTrailCsv);
111: }
112:
113: public static Configuration makeDefaultOfbizConfig()
114: throws TemplateException {
115: Configuration config = Configuration.getDefaultConfiguration();
116: config.setObjectWrapper(BeansWrapper.getDefaultInstance());
117: config.setSetting("datetime_format", "yyyy-MM-dd HH:mm:ss.SSS");
118: return config;
119: }
120:
121: public static String getArg(Map args, String key, Environment env) {
122: Map templateContext = (Map) FreeMarkerWorker.getWrappedObject(
123: "context", env);
124: return getArg(args, key, templateContext);
125: }
126:
127: public static String getArg(Map args, String key,
128: Map templateContext) {
129: //SimpleScalar s = null;
130: Object o = null;
131: String returnVal = null;
132: o = args.get(key);
133: returnVal = (String) unwrap(o);
134: if (returnVal == null) {
135: try {
136: if (templateContext != null) {
137: returnVal = (String) templateContext.get(key);
138: }
139: } catch (ClassCastException e2) {
140: //return null;
141: }
142: }
143: return returnVal;
144: }
145:
146: /**
147: * Gets BeanModel from FreeMarker context and returns the object that it wraps.
148: * @param varName the name of the variable in the FreeMarker context.
149: * @param env the FreeMarker Environment
150: */
151: public static Object getWrappedObject(String varName,
152: Environment env) {
153: Object obj = null;
154: try {
155: obj = env.getVariable(varName);
156: if (obj != null) {
157: if (obj instanceof BeanModel) {
158: BeanModel bean = (BeanModel) obj;
159: obj = bean.getWrappedObject();
160: }
161: }
162: } catch (TemplateModelException e) {
163: Debug.logVerbose(e.getMessage(), module);
164: }
165: return obj;
166: }
167:
168: /**
169: * Gets BeanModel from FreeMarker context and returns the object that it wraps.
170: * @param varName the name of the variable in the FreeMarker context.
171: * @param env the FreeMarker Environment
172: */
173: public static BeanModel getBeanModel(String varName, Environment env) {
174: BeanModel bean = null;
175: try {
176: bean = (BeanModel) env.getVariable(varName);
177: } catch (TemplateModelException e) {
178: Debug.logVerbose(e.getMessage(), module);
179: }
180: return bean;
181: }
182:
183: /*
184: * Tries to find the mime type of the associated content and parent content.
185: *
186: * @param delegator
187: * @param view SubContentDataResourceView
188: * @param parentContent Content entity
189: * @param contentId part of primary key of view. To be used if view is null.
190: * @param dataResourceId part of primary key of view. To be used if view is null.
191: * @param parentContentId primary key of parent content. To be used if parentContent is null;
192: */
193: public static String determineMimeType(GenericDelegator delegator,
194: GenericValue view, GenericValue parentContent,
195: String contentId, String dataResourceId,
196: String parentContentId) throws GenericEntityException {
197: String mimeTypeId = null;
198:
199: if (view != null) {
200: mimeTypeId = (String) view.get("mimeTypeId");
201: Debug.logVerbose("in determineMimeType, mimeType:"
202: + mimeTypeId, "");
203: String drMimeTypeId = (String) view.get("drMimeTypeId");
204: Debug.logVerbose("in determineMimeType, drMimeType:"
205: + drMimeTypeId, "");
206: if (UtilValidate.isNotEmpty(drMimeTypeId)) {
207: mimeTypeId = drMimeTypeId;
208: }
209: Debug.logVerbose("in determineMimeType, view: "
210: + view.get("contentId") + " / "
211: + view.get("drDataResourceId") + " mimeType:"
212: + view.get("drMimeTypeId"), "");
213: }
214:
215: if (UtilValidate.isEmpty(mimeTypeId)) {
216: if (UtilValidate.isNotEmpty(contentId)
217: && UtilValidate.isNotEmpty(dataResourceId)) {
218: view = delegator.findByPrimaryKey(
219: "SubContentDataResourceView", UtilMisc.toMap(
220: "contentId", contentId,
221: "drDataResourceId", dataResourceId));
222: if (view != null) {
223: mimeTypeId = (String) view.get("mimeTypeId");
224: Debug.logVerbose("in determineMimeType, mimeType:"
225: + mimeTypeId, "");
226: String drMimeTypeId = (String) view
227: .get("drMimeTypeId");
228: Debug.logVerbose(
229: "in determineMimeType, drMimeType:"
230: + drMimeTypeId, "");
231: if (UtilValidate.isNotEmpty(drMimeTypeId)) {
232: mimeTypeId = drMimeTypeId;
233: }
234: }
235: }
236: }
237:
238: if (UtilValidate.isEmpty(mimeTypeId)) {
239: if (parentContent != null) {
240: mimeTypeId = (String) parentContent.get("mimeTypeId");
241: }
242: }
243:
244: if (UtilValidate.isEmpty(mimeTypeId)) {
245: if (UtilValidate.isNotEmpty(parentContentId)) {
246: parentContent = delegator.findByPrimaryKey("Content",
247: UtilMisc.toMap("contentId", contentId));
248: if (parentContent != null) {
249: mimeTypeId = (String) parentContent
250: .get("mimeTypeId");
251: }
252: }
253: }
254:
255: return mimeTypeId;
256: }
257:
258: public static Object get(SimpleHash args, String key) {
259: Object returnObj = null;
260: Object o = null;
261: try {
262: o = args.get(key);
263: //Debug.logVerbose("in FM.get, o:" + o + " key:" + key, module);
264: if (o != null) {
265: //Debug.logVerbose("in FM.get, o class:" + o.getClass(), module);
266: }
267: } catch (TemplateModelException e) {
268: Debug.logVerbose(e.getMessage(), module);
269: return returnObj;
270: }
271:
272: returnObj = unwrap(o);
273:
274: if (returnObj == null) {
275: Object ctxObj = null;
276: try {
277: ctxObj = args.get("context");
278: //Debug.logVerbose("in FM.get, ctxObj:" + ctxObj, module);
279: } catch (TemplateModelException e) {
280: Debug.logVerbose(e.getMessage(), module);
281: return returnObj;
282: }
283: Map ctx = null;
284: if (ctxObj instanceof BeanModel) {
285: ctx = (Map) ((BeanModel) ctxObj).getWrappedObject();
286: //Debug.logVerbose("in FM.get, ctx:" + ctx, module);
287: returnObj = ctx.get(key);
288: //Debug.logVerbose("in FM.get..., returnObj:" + returnObj + " key:" + key, module);
289: }
290: /*
291: try {
292: Map templateContext = (Map)FreeMarkerWorker.getWrappedObject("context", env);
293: if (templateContext != null) {
294: returnObj = (String)templateContext.get(key);
295: }
296: } catch(ClassCastException e2) {
297: //return null;
298: }
299: */
300: }
301: return returnObj;
302: }
303:
304: public static Object unwrap(Object o) {
305: Object returnObj = null;
306:
307: if (o instanceof SimpleScalar) {
308: returnObj = o.toString();
309: //Debug.logVerbose("in FM.get, SimpleScalar:" + returnObj, module);
310: } else if (o instanceof BeanModel) {
311: returnObj = ((BeanModel) o).getWrappedObject();
312: //Debug.logVerbose("in FM.get, BeanModel:" + returnObj, module);
313: }
314:
315: return returnObj;
316: }
317:
318: public static void checkForLoop(String path, Map ctx)
319: throws IOException {
320: List templateList = (List) ctx.get("templateList");
321: //Debug.logVerbose("in checkForLoop, templateList:" +templateList, "");
322: //Debug.logVerbose("in checkForLoop, templatePath:" +path, "");
323: if (templateList == null) {
324: templateList = new ArrayList();
325: } else {
326: if (templateList.contains(path)) {
327: Debug.logVerbose("in checkForLoop, " + path
328: + " has been visited.", "");
329: throw new IOException(path
330: + " has already been visited.");
331: }
332: }
333: templateList.add(path);
334: ctx.put("templateList", templateList);
335: return;
336: }
337:
338: public static Map createEnvironmentMap(Environment env) {
339: Map templateRoot = new HashMap();
340: Set varNames = null;
341: try {
342: varNames = env.getKnownVariableNames();
343: } catch (TemplateModelException e1) {
344: Debug
345: .logError(
346: e1,
347: "Error getting FreeMarker variable names, will not put pass current context on to sub-content",
348: module);
349: }
350: if (varNames != null) {
351: Iterator varNameIter = varNames.iterator();
352: while (varNameIter.hasNext()) {
353: String varName = (String) varNameIter.next();
354: templateRoot.put(varName, FreeMarkerWorker
355: .getWrappedObject(varName, env));
356: }
357: }
358: return templateRoot;
359: }
360:
361: public static void renderTemplate(String templateIdString,
362: String template, Map context, Writer outWriter)
363: throws TemplateException, IOException {
364: Reader templateReader = new StringReader(template);
365: renderTemplate(templateIdString, templateReader, context,
366: outWriter);
367: }
368:
369: public static void renderTemplate(String templateIdString,
370: Reader templateReader, Map context, Writer outWriter)
371: throws TemplateException, IOException {
372: if (context == null) {
373: context = new HashMap();
374: }
375:
376: Configuration config = makeDefaultOfbizConfig();
377: Template template = new Template(templateIdString,
378: templateReader, config);
379:
380: // add the OFBiz transforms/methods
381: addAllOfbizTransforms(context);
382:
383: // process the template with the given data and write
384: // the email body to the String buffer
385: template.process(context, outWriter);
386: }
387:
388: public static void traceNodeTrail(String lbl, List nodeTrail) {
389:
390: if (!Debug.verboseOn()) {
391: return;
392: }
393: if (nodeTrail == null) {
394: Debug.logVerbose("[" + lbl + "] nodeTrail is null.", "");
395: return;
396: }
397: String s = "";
398: int sz = nodeTrail.size();
399: s = "nTsz:" + sz;
400: if (sz > 0) {
401: Map cN = (Map) nodeTrail.get(sz - 1);
402: if (cN != null) {
403: String cid = (String) cN.get("contentId");
404: s += " cN[" + cid + "]";
405: List kids = (List) cN.get("kids");
406: int kSz = (kids == null) ? 0 : kids.size();
407: s += " kSz:" + kSz;
408: Boolean isPick = (Boolean) cN.get("isPick");
409: s += " isPick:" + isPick;
410: }
411: }
412: Debug.logVerbose("[" + lbl + "] " + s, "");
413: return;
414: }
415:
416: public static String logMap(String lbl, Map map, int indent) {
417:
418: String sep = ":";
419: String eol = "\n";
420: String spc = "";
421: for (int i = 0; i < indent; i++)
422: spc += " ";
423: String s = (lbl != null) ? lbl : "";
424: s += "=" + indent + "==>" + eol;
425: Set keySet = map.keySet();
426: Iterator it = keySet.iterator();
427: while (it.hasNext()) {
428: String key = (String) it.next();
429: if ("request response session".indexOf(key) < 0) {
430: Object obj = map.get(key);
431: s += spc + key + sep;
432: ;
433: if (obj instanceof GenericValue) {
434: GenericValue gv = (GenericValue) obj;
435: GenericPK pk = gv.getPrimaryKey();
436: s += logMap("GMAP[" + key + " name:"
437: + pk.getEntityName() + "]", pk, indent + 1);
438: } else if (obj instanceof List) {
439: s += logList("LIST[" + ((List) obj).size() + "]",
440: (List) obj, indent + 1);
441: } else if (obj instanceof Map) {
442: s += logMap("MAP[" + key + "]", (Map) obj,
443: indent + 1);
444: } else if (obj != null) {
445: s += obj + sep + obj.getClass() + eol;
446: } else {
447: s += eol;
448: }
449: }
450: }
451: return s + eol + eol;
452: }
453:
454: public static String logList(String lbl, List lst, int indent) {
455:
456: String sep = ":";
457: String eol = "\n";
458: String spc = "";
459: if (lst == null)
460: return "";
461: int sz = lst.size();
462: for (int i = 0; i < indent; i++)
463: spc += " ";
464: String s = (lbl != null) ? lbl : "";
465: s += "=" + indent + "==> sz:" + sz + eol;
466: Iterator it = lst.iterator();
467: while (it.hasNext()) {
468: Object obj = it.next();
469: s += spc;
470: if (obj instanceof GenericValue) {
471: GenericValue gv = (GenericValue) obj;
472: GenericPK pk = gv.getPrimaryKey();
473: s += logMap("MAP[name:" + pk.getEntityName() + "]", pk,
474: indent + 1);
475: } else if (obj instanceof List) {
476: s += logList("LIST[" + ((List) obj).size() + "]",
477: (List) obj, indent + 1);
478: } else if (obj instanceof Map) {
479: s += logMap("MAP[]", (Map) obj, indent + 1);
480: } else if (obj != null) {
481: s += obj + sep + obj.getClass() + eol;
482: } else {
483: s += eol;
484: }
485: }
486: return s + eol + eol;
487: }
488:
489: public static Map saveValues(Map context, String[] saveKeyNames) {
490: Map saveMap = new HashMap();
491: for (int i = 0; i < saveKeyNames.length; i++) {
492: String key = (String) saveKeyNames[i];
493: Object o = context.get(key);
494: if (o instanceof Map)
495: o = new HashMap((Map) o);
496: else if (o instanceof List)
497: o = new ArrayList((List) o);
498: saveMap.put(key, o);
499: if (key.equals("globalNodeTrail")) {
500: Debug.logInfo("saveValues,key:" + key + " csv:"
501: + nodeTrailToCsv((List) o), "");
502: }
503: if (key.equals("nodeTrail")) {
504: Debug.logInfo("saveValues,key:" + key + " csv:"
505: + nodeTrailToCsv((List) o), "");
506: }
507: }
508: return saveMap;
509: }
510:
511: public static void reloadValues(Map context, Map saveValues) {
512: Set keySet = saveValues.keySet();
513: Iterator it = keySet.iterator();
514: while (it.hasNext()) {
515: String key = (String) it.next();
516: Object o = saveValues.get(key);
517: context.put(key, saveValues.get(key));
518: if (key.equals("globalNodeTrail")) {
519: Debug.logInfo("reloadValues,key:" + key + " csv:"
520: + nodeTrailToCsv((List) o), "");
521: }
522: if (key.equals("nodeTrail")) {
523: Debug.logInfo("reloadValues,key:" + key + " csv:"
524: + nodeTrailToCsv((List) o), "");
525: }
526: }
527: return;
528: }
529:
530: public static void removeValues(Map context, String[] removeKeyNames) {
531: for (int i = 0; i < removeKeyNames.length; i++) {
532: String key = (String) removeKeyNames[i];
533: context.remove(key);
534: }
535: return;
536: }
537:
538: public static void overrideWithArgs(Map ctx, Map args) {
539: Set keySet = args.keySet();
540: Iterator it = keySet.iterator();
541: while (it.hasNext()) {
542: String key = (String) it.next();
543: Object obj = args.get(key);
544: if (obj != null) {
545: Object unwrappedObj = unwrap(obj);
546: if (unwrappedObj == null)
547: unwrappedObj = obj;
548: Debug.logVerbose("in overrideWithArgs, key:" + key
549: + " uObj:" + unwrappedObj, "");
550: ctx.put(key, unwrappedObj.toString());
551: } else {
552: ctx.put(key, null);
553: }
554: }
555: return;
556: }
557:
558: public static void convertContext(Map ctx) {
559: Set keySet = ctx.keySet();
560: Iterator it = keySet.iterator();
561: while (it.hasNext()) {
562: String key = (String) it.next();
563: Object obj = ctx.get(key);
564: if (obj != null) {
565: Object unwrappedObj = unwrap(obj);
566: if (unwrappedObj != null) {
567: ctx.put(key, unwrappedObj);
568: }
569: }
570: }
571: return;
572: }
573:
574: public static void getSiteParameters(HttpServletRequest request,
575: Map ctx) {
576:
577: if (request == null)
578: return;
579: ServletContext servletContext = request.getSession()
580: .getServletContext();
581: String rootDir = (String) ctx.get("rootDir");
582: String webSiteId = (String) ctx.get("webSiteId");
583: String https = (String) ctx.get("https");
584: if (UtilValidate.isEmpty(rootDir)) {
585: rootDir = servletContext.getRealPath("/");
586: ctx.put("webSiteId", webSiteId);
587: }
588: if (UtilValidate.isEmpty(webSiteId)) {
589: webSiteId = (String) servletContext
590: .getAttribute("webSiteId");
591: ctx.put("https", https);
592: }
593: if (UtilValidate.isEmpty(https)) {
594: https = (String) servletContext.getAttribute("https");
595: ctx.put("rootDir", rootDir);
596: }
597: return;
598: }
599:
600: public static Map makeNode(GenericValue this Content) {
601: Map this Node = new HashMap();
602: this Node.put("value", this Content);
603: this Node.put("contentId", this Content.get("contentId"));
604: this Node.put("contentTypeId", this Content.get("contentTypeId"));
605: return this Node;
606: }
607:
608: public static String nodeTrailToCsv(List nodeTrail) {
609:
610: if (nodeTrail == null)
611: return "";
612: StringBuffer csv = new StringBuffer();
613: Iterator it = nodeTrail.iterator();
614: while (it.hasNext()) {
615: if (csv.length() > 0)
616: csv.append(",");
617: Map node = (Map) it.next();
618: String contentId = (String) node.get("contentId");
619: csv.append(contentId);
620: }
621: return csv.toString();
622: }
623:
624: public static List csvToList(String csv, GenericDelegator delegator) {
625:
626: ArrayList outList = new ArrayList();
627: List contentIdList = StringUtil.split(csv, ",");
628: GenericValue content = null;
629: String contentId = null;
630: String contentName = null;
631: ArrayList values = null;
632: Iterator it = contentIdList.iterator();
633: while (it.hasNext()) {
634: contentId = (String) it.next();
635: try {
636: content = delegator.findByPrimaryKeyCache("Content",
637: UtilMisc.toMap("contentId", contentId));
638: } catch (GenericEntityException e) {
639: Debug.logError(e.getMessage(), module);
640: return new ArrayList();
641: }
642: contentName = (String) content.get("contentName");
643: values = new ArrayList();
644: values.add(contentId);
645: values.add(contentName);
646: outList.add(values);
647: }
648: return outList;
649: }
650: }
|