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));
}