I thought that I should have takeen into account case unsensitive (but anyway, as I said maybe there is a better/more general solution)

Jacques

From: "David E Jones" <david.jo...@hotwaxmedia.com>

I'm looking into this now.

-David


On Feb 8, 2009, at 9:21 AM, Jacques Le Roux wrote:

This causes an issue when rendering a javascript variable build in  groovy
Commenting out lines 71-73 of HtmlWidget.java solves the problem.
Please see Giant Widget with variant explosion in ecommerce when  viewing 
details for an example.
I would suggest
          if (object instanceof String) {
              if (!((String) object).contains("<script language= 
\"JavaScript\">")) {
                  return new StringHtmlWrapperForFtl((String)  object, this);
              }
          }


but not sue it's the best way (it works of course)

Jacques

From: <jone...@apache.org>
Author: jonesde
Date: Sun Feb  8 07:40:40 2009
New Revision: 742013

URL: http://svn.apache.org/viewvc?rev=742013&view=rev
Log:
Implemented StringModel extension and BeansWrapper extension to load it in order to encode strings for HTML use; this is only done throught the HtmlWidget class that is part of the screen widget, so won't interfere with other FTL uses; note that there is other experimental code in here for wrapping the GenericValue object for html encoding, but that option wasn't very complete so went this way instead; this option behaves better and is more transparent than that escape x as x?html option for FTL files; there are also a few cleanups of typos and things in here; note that this means we have a different Configuration object and so a different template cache, and so we have different cache settings and such; after applying this I found a few places that encoded things they shouldn't but for the most part it is pretty good; will be committing some changes in applications in a bit to resolve a couple of these issues in ecommerce; all should watch out for funny things showing up as HTML text instead of being interpreted by the browser as HTML, meaning it was encoded; in extreme cases just comment out lines 71-73 of HtmlWidget.java to turn off this encoding

Added:
  ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ 
GenericValueHtmlWrapper.java   (with props)
Modified:
  ofbiz/trunk/framework/base/config/cache.properties
  ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/ 
FreeMarkerWorker.java
  ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericEntity.java
  ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java
  ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ RequestHandler.java
  ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/ HtmlWidget.java

Modified: ofbiz/trunk/framework/base/config/cache.properties
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/config/cache.properties?rev=742013&r1=742012&r2=742013&view=diff
= = = = = = = = = 
=====================================================================
--- ofbiz/trunk/framework/base/config/cache.properties (original)
+++ ofbiz/trunk/framework/base/config/cache.properties Sun Feb  8  07:40:40 2009
@@ -91,8 +91,9 @@
widget.tree.locationResource.expireTime=10000
widget.tree.webappResource.expireTime=10000

-template.ftl.general.expireTime=10000
template.ftl.location.expireTime=10000
+template.ftl.general.expireTime=10000
+widget.screen.template.ftl.general.expireTime=10000

ModelDataFile.expireTime=10000


Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ 
template/FreeMarkerWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/FreeMarkerWorker.java?rev=742013&r1=742012&r2=742013&view=diff
= = = = = = = = = 
=====================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/ 
FreeMarkerWorker.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/ 
FreeMarkerWorker.java Sun Feb  8 07:40:40 2009
@@ -62,7 +62,6 @@
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
-//import com.clarkware.profiler.Profiler;

/** FreeMarkerWorker - Freemarker Template Engine Utilities.
*
@@ -73,17 +72,19 @@

// use soft references for this so that things from Content records don't kill all of our memory, or maybe not for performance reasons... hmmm, leave to config file... public static UtilCache<String, Template> cachedTemplates = new UtilCache<String, Template>("template.ftl.general", 0, 0, false);
-    protected static Configuration defaultOfbizConfig = new  Configuration();
+    protected static BeansWrapper defaultOfbizWrapper =  
BeansWrapper.getDefaultInstance();
+    protected static Configuration defaultOfbizConfig =  
makeConfiguration(defaultOfbizWrapper);

-    static {
-        BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
-        defaultOfbizConfig.setObjectWrapper(wrapper);
-        defaultOfbizConfig.setSharedVariable("Static",  
wrapper.getStaticModels());
-        defaultOfbizConfig.setLocalizedLookup(false);
-        defaultOfbizConfig.setTemplateLoader(new  FlexibleTemplateLoader());
+    public static Configuration makeConfiguration(BeansWrapper  wrapper) {
+        Configuration newConfig = new Configuration();
+
+        newConfig.setObjectWrapper(wrapper);
+        newConfig.setSharedVariable("Static",  wrapper.getStaticModels());
+        newConfig.setLocalizedLookup(false);
+        newConfig.setTemplateLoader(new FlexibleTemplateLoader());
       try {
-            defaultOfbizConfig.setSetting("datetime_format", "yyyy- MM-dd 
HH:mm:ss.SSS");
-            defaultOfbizConfig.setSetting("number_format",  "0.##########");
+            newConfig.setSetting("datetime_format", "yyyy-MM-dd  
HH:mm:ss.SSS");
+            newConfig.setSetting("number_format", "0.##########");
       } catch (TemplateException e) {
           Debug.logError("Unable to set date/time and number  formats in 
FreeMarker: " + e, module);
       }
@@ -103,23 +104,25 @@
           if (props == null || props.isEmpty()) {
               Debug.logError("Unable to locate properties file " +  
propertyURL, module);
           } else {
-                loadTransforms(loader, props);
+                loadTransforms(loader, props, newConfig);
           }
       }
+
+        return newConfig;
   }

   /**
    * Protected helper method.
    */
-    protected static void loadTransforms(ClassLoader loader,  Properties 
props) {
+    protected static void loadTransforms(ClassLoader loader,  Properties 
props, Configuration config) {
       for (Iterator<Object> i = props.keySet().iterator();  i.hasNext();) {
-            String key = (String)i.next();
+            String key = (String) i.next();
           String className = props.getProperty(key);
           if (Debug.verboseOn()) {
               Debug.logVerbose("Adding FTL Transform " + key + "  with class " 
+ className, module);
           }
           try {
-                defaultOfbizConfig.setSharedVariable(key,  
loader.loadClass(className).newInstance());
+                config.setSharedVariable(key,  
loader.loadClass(className).newInstance());
           } catch (Exception e) {
               Debug.logError(e, "Could not pre-initialize  dynamically loaded class: " + 
className + ": " + e, module);
           }
@@ -195,7 +198,7 @@
       // FIXME: the casting from Appendable to Writer is a  temporary fix that 
could cause a
       //        run time error if in the future we will pass a  different 
class to the method
       //        (such as a StringBuffer).
-        Environment env =  template.createProcessingEnvironment(context, 
(Writer)outWriter);
+        Environment env =  template.createProcessingEnvironment(context, 
(Writer) outWriter);
       applyUserSettings(env, context);
       env.process();
       return env;
@@ -261,16 +264,20 @@
    * @param templateLocation Location of the template - file path  or URL
    */
   public static Template getTemplate(String templateLocation)  throws 
TemplateException, IOException {
-        Template template = (Template)  cachedTemplates.get(templateLocation);
+        return getTemplate(templateLocation, cachedTemplates,  
defaultOfbizConfig);
+    }
+
+ public static Template getTemplate(String templateLocation, UtilCache<String, Template> cache, Configuration config) throws TemplateException, IOException {
+        Template template = (Template) cache.get(templateLocation);
       if (template == null) {
-            synchronized (cachedTemplates) {
-                template = (Template)  cachedTemplates.get(templateLocation);
+            synchronized (cache) {
+                template = (Template) cache.get(templateLocation);
               if (template == null) {
                   // only make the reader if we need it, and then  close it 
right after!
                   Reader templateReader =  makeReader(templateLocation);
-                    template = new Template(templateLocation,  templateReader, 
defaultOfbizConfig);
+                    template = new Template(templateLocation,  templateReader, 
config);
                   templateReader.close();
-                    cachedTemplates.put(templateLocation, template);
+                    cache.put(templateLocation, template);
               }
           }
       }

Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericEntity.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericEntity.java?rev=742013&r1=742012&r2=742013&view=diff
= = = = = = = = = 
=====================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericEntity.java 
(original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericEntity.java Sun 
Feb  8 07:40:40 2009
@@ -142,21 +142,21 @@
   /** Creates new GenericEntity */
   protected void init(ModelEntity modelEntity) {
       if (modelEntity == null) {
-            throw new IllegalArgumentException("Cannont create a  GenericEntity 
with a null modelEntity parameter");
+            throw new IllegalArgumentException("Cannot create a  GenericEntity with 
a null modelEntity parameter");
       }
       this.modelEntity = modelEntity;
       this.entityName = modelEntity.getEntityName();

       // check some things
       if (this.entityName == null) {
- throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity parameter"); + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity parameter");
       }
   }

   /** Creates new GenericEntity from existing Map */
   protected void init(ModelEntity modelEntity, Map<String, ?  extends Object> 
fields) {
       if (modelEntity == null) {
-            throw new IllegalArgumentException("Cannont create a  GenericEntity 
with a null modelEntity parameter");
+            throw new IllegalArgumentException("Cannot create a  GenericEntity with 
a null modelEntity parameter");
       }
       this.modelEntity = modelEntity;
       this.entityName = modelEntity.getEntityName();
@@ -164,14 +164,14 @@

       // check some things
       if (this.entityName == null) {
- throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity parameter"); + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity parameter");
       }
   }

   /** Creates new GenericEntity from existing Map */
   protected void init(ModelEntity modelEntity, Object  singlePkValue) {
       if (modelEntity == null) {
-            throw new IllegalArgumentException("Cannont create a  GenericEntity 
with a null modelEntity parameter");
+            throw new IllegalArgumentException("Cannot create a  GenericEntity with 
a null modelEntity parameter");
       }
       if (modelEntity.getPksSize() != 1) {
           throw new IllegalArgumentException("Cannot create a  GenericEntity with 
more than one primary key field");
@@ -182,25 +182,22 @@

       // check some things
       if (this.entityName == null) {
- throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity parameter"); + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity parameter");
       }
   }

   /** Copy Constructor: Creates new GenericEntity from existing  GenericEntity 
*/
   protected void init(GenericEntity value) {
-        if (value.modelEntity == null) {
- throw new IllegalArgumentException("Cannont create a GenericEntity from another GenericEntity with a null modelEntity in the value parameter");
+        // check some things
+        if (value.entityName == null) {
+ throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity parameter");
       }
-        this.entityName = value.modelEntity.getEntityName();
+        this.entityName = value.getEntityName();
+ // NOTE: could call getModelEntity to insure we have a value, just in case the value passed in has been serialized, but might as well leave it null to keep the object light if it isn't there
       this.modelEntity = value.modelEntity;
       if (value.fields != null) this.fields.putAll(value.fields);
       this.delegatorName = value.delegatorName;
       this.internalDelegator = value.internalDelegator;
-
-        // check some things
-        if (this.entityName == null) {
- throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity parameter");
-        }
   }

   public void reset() {

Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValue.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java?rev=742013&r1=742012&r2=742013&view=diff
= = = = = = = = = 
=====================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValue.java 
(original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValue.java Sun 
Feb  8 07:40:40 2009
@@ -24,8 +24,8 @@
import java.util.List;
import java.util.Map;

-import javolution.lang.Reusable;
import javolution.context.ObjectFactory;
+import javolution.lang.Reusable;
import javolution.util.FastMap;

import org.ofbiz.base.util.Debug;
@@ -33,7 +33,6 @@
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityFieldMap;
-import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.model.ModelKeyMap;
import org.ofbiz.entity.model.ModelRelation;
@@ -44,6 +43,7 @@
* Generic Entity Value Object - Handles persistence for any defined  entity.
*
*/
+...@suppresswarnings("serial")
public class GenericValue extends GenericEntity implements Reusable {

   public static final GenericValue NULL_VALUE = new  NullGenericValue();

Added: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ 
GenericValueHtmlWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java?rev=742013&view=auto
= = = = = = = = = 
=====================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ 
GenericValueHtmlWrapper.java (added)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ 
GenericValueHtmlWrapper.java Sun Feb  8 07:40:40 2009
@@ -0,0 +1,105 @@
+/ 
*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+  
*******************************************************************************/
+
+package org.ofbiz.entity;
+
+
+import javolution.context.ObjectFactory;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.StringUtil;
+
+import freemarker.ext.beans.BeansWrapper;
+import freemarker.ext.beans.MapModel;
+import freemarker.ext.beans.StringModel;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+
+
+/**
+ * Generic Entity Value Object - Handles persistence for any  defined entity.
+ * WARNING: This object is experimental!
+ *
+ */
+...@suppresswarnings("serial")
+public class GenericValueHtmlWrapper extends GenericValue {
+ protected static final ObjectFactory<GenericValueHtmlWrapper> genericValueHtmlWrapperFactory = new ObjectFactory<GenericValueHtmlWrapper>() {
+        protected GenericValueHtmlWrapper create() {
+            return new GenericValueHtmlWrapper();
+        }
+    };
+
+    /** Creates new GenericValueHtmlWrapper from existing  GenericValue */
+    public static GenericValueHtmlWrapper create(GenericValue  value) {
+        GenericValueHtmlWrapper newValue =  
genericValueHtmlWrapperFactory.object();
+        try {
+            newValue.init(value);
+        } catch (RuntimeException e) {
+            Debug.logError(e, "Error in init for clone of value: "  + value, 
module);
+            throw e;
+        }
+        return newValue;
+    }
+
+ /* NOTE: this is NOT used because there are certain FTL files that call services and things, and this messes those up, so only overriding the Map.get(Object) method to get use of this as a Map + * Override the basic get method, which all other get methods call so we only need to do this one (though most important for the Map.get(Object) and the getString() methods
+    public Object get(String name) {
+        Object value = super.get(name);
+        if (value instanceof String) {
+            return StringUtil.htmlEncoder.encode((String) value);
+        } else {
+            return value;
+        }
+    }*/
+
+    public Object get(Object name) {
+        Object value = super.get(name);
+        if (value instanceof String) {
+            return StringUtil.htmlEncoder.encode((String) value);
+        } else {
+            return value;
+        }
+    }
+
+    // another experimental object, this one specifically for FTL
+    public static class GenericValueHtmlWrapperForFtl extends  MapModel {
+        public GenericValueHtmlWrapperForFtl(GenericValue gv,  BeansWrapper 
wrapper) {
+            super(gv, wrapper);
+        }
+
+        public TemplateModel get(String key) {
+            TemplateModel tm = null;
+            try {
+                tm = super.get(key);
+            } catch (TemplateModelException e) {
+                Debug.logError(e, "Error getting Map with key [" +  key + "]: 
" + e.toString(), module);
+            }
+            if (tm instanceof StringModel) {
+                String original = ((StringModel) tm).getAsString();
+                if (original != null) {
+                    String encoded =  StringUtil.htmlEncoder.encode(original);
+                    if (!original.equals(encoded)) {
+                        return new StringModel(encoded,  this.wrapper);
+                    }
+                }
+            }
+            return tm;
+        }
+    }
+}

Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ 
GenericValueHtmlWrapper.java
------------------------------------------------------------------------------
  svn:eol-style = native

Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ 
GenericValueHtmlWrapper.java
------------------------------------------------------------------------------
  svn:keywords = "Date Rev Author URL Id"

Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ 
GenericValueHtmlWrapper.java
------------------------------------------------------------------------------
  svn:mime-type = text/plain

Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ 
RequestHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java?rev=742013&r1=742012&r2=742013&view=diff
= = = = = = = = = 
=====================================================================
--- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ 
RequestHandler.java (original)
+++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ 
RequestHandler.java Sun Feb  8 07:40:40 2009
@@ -950,7 +950,9 @@
   public boolean trackStats(HttpServletRequest request) {
       if  (!"false".equalsIgnoreCase(context.getInitParameter("track- 
serverhit"))) {
           String uriString =  
RequestHandler.getRequestUri(request.getPathInfo());
-            return  
controllerConfig.requestMapMap.get(uriString).trackServerHit;
+            ConfigXMLReader.RequestMap requestMap =  
controllerConfig.requestMapMap.get(uriString);
+            if (requestMap == null) return false;
+            return requestMap.trackServerHit;
       } else {
           return false;
       }
@@ -959,7 +961,9 @@
   public boolean trackVisit(HttpServletRequest request) {
       if  (!"false".equalsIgnoreCase(context.getInitParameter("track- 
visit"))) {
           String uriString =  
RequestHandler.getRequestUri(request.getPathInfo());
-            return  controllerConfig.requestMapMap.get(uriString).trackVisit;
+            ConfigXMLReader.RequestMap requestMap =  
controllerConfig.requestMapMap.get(uriString);
+            if (requestMap == null) return false;
+            return requestMap.trackVisit;
       } else {
           return false;
       }

Modified: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/ 
HtmlWidget.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java?rev=742013&r1=742012&r2=742013&view=diff
= = = = = = = = = 
=====================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/ HtmlWidget.java 
(original)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/ HtmlWidget.java 
Sun Feb  8 07:40:40 2009
@@ -21,7 +21,6 @@
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;

@@ -29,9 +28,11 @@

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
+import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.cache.UtilCache;
import org.ofbiz.base.util.collections.MapStack;
import org.ofbiz.base.util.string.FlexibleStringExpander;
import org.ofbiz.base.util.template.FreeMarkerWorker;
@@ -39,7 +40,13 @@
import org.ofbiz.widget.html.HtmlWidgetRenderer;
import org.w3c.dom.Element;

+import freemarker.ext.beans.BeansWrapper;
+import freemarker.ext.beans.StringModel;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;

/**
* Widget Library - Screen model HTML class.
@@ -47,6 +54,37 @@
@SuppressWarnings("serial")
public class HtmlWidget extends ModelScreenWidget {
   public static final String module = HtmlWidget.class.getName();
+
+ public static UtilCache<String, Template> specialTemplateCache = new UtilCache<String, Template>("widget.screen.template.ftl.general", 0, 0, false);
+    protected static BeansWrapper specialBeansWrapper = new  ExtendedWrapper();
+    protected static Configuration specialConfig =  
FreeMarkerWorker.makeConfiguration(specialBeansWrapper);
+
+    // not sure if this is the best way to get FTL to use my fancy  MapModel 
derivative, but should work at least...
+    public static class ExtendedWrapper extends BeansWrapper {
+        public TemplateModel wrap(Object object) throws  
TemplateModelException {
+            /* NOTE: don't use this and the  StringHtmlWrapperForFtl or things 
will be double-encoded
+            if (object instanceof GenericValue) {
+                return new  GenericValueHtmlWrapperForFtl((GenericValue) 
object, this);
+            }*/
+            // This StringHtmlWrapperForFtl option seems to be the  best option
+            // and handles most things without causing too many  problems
+            if (object instanceof String) {
+                return new StringHtmlWrapperForFtl((String)  object, this);
+            }
+            return super.wrap(object);
+        }
+    }
+
+    public static class StringHtmlWrapperForFtl extends  StringModel {
+        public StringHtmlWrapperForFtl(String str, BeansWrapper  wrapper) {
+            super(str, wrapper);
+        }
+        public String getAsString() {
+            return  StringUtil.htmlEncoder.encode(super.getAsString());
+        }
+    }
+
+    // End Static, begin class section

   protected List<ModelScreenWidget> subWidgets = new  
ArrayList<ModelScreenWidget>();

@@ -87,6 +125,64 @@
           throw new IllegalArgumentException("Template location is  empty");
       }

+
+        /*
+        //  = = 
=====================================================================
+        // Go through the context and find GenericValue objects  and wrap them
+
+        // NOTE PROBLEM: there are still problems with this as it  gets some 
things
+        // but does not get non-entity data including lots of  strings
+        // directly in the context or things prepared or derived  right in
+        // the FTL file, like the results of service calls, etc;  we could
+        // do something more aggressive to encode and wrap  EVERYTHING in
+        // the context, but I've been thinking that even this is  too much
+        // overhead and that would be crazy
+
+        // NOTE ALTERNATIVE1: considering instead to use the FTL  features to 
wrap
+        // everything in an <#escape x as x?html>...</#escape>,  but that could
+        // cause problems with ${} expansions that have HTML in  them, 
including:
+        // included screens (using ${screens.render(...)}),  content that 
should
+        // have HTML in it (lots of general, product, category,  etc content), 
etc
+
+        // NOTE ALTERNATIVE2: kind of like the "#escape X as x? html" option,
+        // implement an FTL *Model class and load it through a  ObjectWrapper
+        // FINAL NOTE: after testing all of these alternatives,  this one seems
+        // to behave the best, so going with that for now.
+
+        // isolate the scope so these wrapper objects go away  after rendering 
is done
+        MapStack<String> contextMs;
+        if (!(context instanceof MapStack)) {
+            contextMs = MapStack.create(context);
+            context = contextMs;
+        } else {
+            contextMs = UtilGenerics.cast(context);
+        }
+
+        contextMs.push();
+        for(Map.Entry<String, Object> mapEntry:  contextMs.entrySet()) {
+            Object value = mapEntry.getValue();
+            if (value instanceof GenericValue) {
+                contextMs.put(mapEntry.getKey(),  
GenericValueHtmlWrapper.create((GenericValue) value));
+            } else if (value instanceof List) {
+                if (((List) value).size() > 0 && ((List)  value).get(0) 
instanceof GenericValue) {
+                    List<GenericValue> theList =  (List<GenericValue>) value;
+                    List<GenericValueHtmlWrapper> newList =  
FastList.newInstance();
+                    for (GenericValue gv: theList) {
+                         newList.add(GenericValueHtmlWrapper.create(gv));
+                    }
+                    contextMs.put(mapEntry.getKey(), newList);
+                }
+            }
+            // TODO and NOTE: should get most stuff, but we could  support Maps
+            // and Lists in Maps and such; that's tricky because  we have to go
+            // through the entire Map and not just one entry, and  we would
+            // have to shallow copy the whole Map too
+
+        }
+        // this line goes at the end of the method, but moved up  here to be 
part of the big comment about this
+        contextMs.pop();
+         */
+
       if (location.endsWith(".ftl")) {
           try {
               Map<String, ? extends Object> parameters =  
UtilGenerics.checkMap(context.get("parameters"));
@@ -94,7 +190,11 @@
               if (insertWidgetBoundaryComments) {
                    writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin",  
"Template", location));
               }
-                 FreeMarkerWorker.renderTemplateAtLocation(location, context, 
writer);
+
+                // FreeMarkerWorker.renderTemplateAtLocation(location, 
context, writer);
+                Template template =  FreeMarkerWorker.getTemplate(location, 
specialTemplateCache,  specialConfig);
+                FreeMarkerWorker.renderTemplate(template, context,  writer);
+
               if (insertWidgetBoundaryComments) {
                    writer.append(HtmlWidgetRenderer.formatBoundaryComment("End",  
"Template", location));
               }




Reply via email to