From 1f9bcac9b1358e96b5a508e78e0ccd54e618599e Mon Sep 17 00:00:00 2001 From: ryounes Date: Mon, 8 Aug 2011 22:28:55 +0000 Subject: [PATCH] NIHVIVO-3114 Fix problems with dump of IndividualTemplateModel.qrData() --- .../freemarker/IndividualController.java | 2 +- .../beanswrappers}/ReadOnlyBeansWrapper.java | 26 ++++++++++++++++--- .../ext/beans/WrapperExtractor.java | 3 +++ .../ext/dump/BaseDumpDirective.java | 24 ++++++++++------- 4 files changed, 41 insertions(+), 14 deletions(-) rename webapp/src/{freemarker/ext/beans => edu/cornell/mannlib/vitro/webapp/web/beanswrappers}/ReadOnlyBeansWrapper.java (64%) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java index b2814b228..fafba7708 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java @@ -58,9 +58,9 @@ import edu.cornell.mannlib.vitro.webapp.utils.NamespaceMapper; import edu.cornell.mannlib.vitro.webapp.utils.NamespaceMapperFactory; import edu.cornell.mannlib.vitro.webapp.utils.jena.ExtendedLinkedDataUtils; import edu.cornell.mannlib.vitro.webapp.web.ContentType; +import edu.cornell.mannlib.vitro.webapp.web.beanswrappers.ReadOnlyBeansWrapper; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.IndividualTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individuallist.ListedIndividual; -import freemarker.ext.beans.ReadOnlyBeansWrapper; /** * Handles requests for entity information. diff --git a/webapp/src/freemarker/ext/beans/ReadOnlyBeansWrapper.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/beanswrappers/ReadOnlyBeansWrapper.java similarity index 64% rename from webapp/src/freemarker/ext/beans/ReadOnlyBeansWrapper.java rename to webapp/src/edu/cornell/mannlib/vitro/webapp/web/beanswrappers/ReadOnlyBeansWrapper.java index af40a99e2..e3f921b58 100644 --- a/webapp/src/freemarker/ext/beans/ReadOnlyBeansWrapper.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/beanswrappers/ReadOnlyBeansWrapper.java @@ -1,16 +1,20 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ -package freemarker.ext.beans; +package edu.cornell.mannlib.vitro.webapp.web.beanswrappers; import java.lang.reflect.Method; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -/** BeansWrapper that is more restrictive than EXPOSE_SAFE, by +import freemarker.ext.beans.BeansWrapper; +import freemarker.ext.beans.BeansWrapper.MethodAppearanceDecision; + +/** A BeansWrapper that is more restrictive than EXPOSE_SAFE, by * exposing getters but not setters. A setter is defined for this * purpose as a method that returns void, or whose name - * starts with "set". + * starts with "set". It also hides built-in methods of Java + * utility classes like Map.put(), etc. * * @author rjy7 * @@ -27,12 +31,26 @@ public class ReadOnlyBeansWrapper extends BeansWrapper { @Override protected void finetuneMethodAppearance(Class cls, Method method, MethodAppearanceDecision decision) { - // How to define a setter? This is an approximation: a method whose name + // How to define a setter? This is a weak approximation: a method whose name // starts with "set" or returns void. if ( method.getName().startsWith("set") ) { decision.setExposeMethodAs(null); + } else if ( method.getReturnType().getName().equals("void") ) { decision.setExposeMethodAs(null); + + } else { + + Class declaringClass = method.getDeclaringClass(); + if (declaringClass.equals(java.lang.Object.class)) { + decision.setExposeMethodAs(null); + + } else { + Package pkg = declaringClass.getPackage(); + if (pkg.getName().equals("java.util")) { + decision.setExposeMethodAs(null); + } + } } } diff --git a/webapp/src/freemarker/ext/beans/WrapperExtractor.java b/webapp/src/freemarker/ext/beans/WrapperExtractor.java index 6ce3f4cc1..a1c63e185 100644 --- a/webapp/src/freemarker/ext/beans/WrapperExtractor.java +++ b/webapp/src/freemarker/ext/beans/WrapperExtractor.java @@ -2,6 +2,8 @@ package freemarker.ext.beans; +import java.util.Set; + /** * Class to extract wrapper used to wrap an object into a template model object. * Used as workaround to gap in Freemarker template model API (can't get wrapper @@ -16,4 +18,5 @@ public class WrapperExtractor { public static int getWrapperExposureLevel(BeanModel model) { return model.wrapper.getExposureLevel(); } + } diff --git a/webapp/src/freemarker/ext/dump/BaseDumpDirective.java b/webapp/src/freemarker/ext/dump/BaseDumpDirective.java index 0d2e12a79..18c8778a5 100644 --- a/webapp/src/freemarker/ext/dump/BaseDumpDirective.java +++ b/webapp/src/freemarker/ext/dump/BaseDumpDirective.java @@ -25,6 +25,7 @@ import freemarker.core.Environment; import freemarker.ext.beans.BeanModel; import freemarker.ext.beans.BeansWrapper; import freemarker.ext.beans.CollectionModel; +import freemarker.ext.beans.MapModel; import freemarker.ext.beans.SimpleMethodModel; import freemarker.ext.beans.StringModel; import freemarker.ext.beans.WrapperExtractor; @@ -175,6 +176,7 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel { } private Map getDump(TemplateModel model) throws TemplateModelException { + Map map = new HashMap(); // Don't return null if model == null. We still want to send the map to the template. @@ -308,7 +310,8 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel { if ( unwrappedModel instanceof Map ) { return getMapDump(model); } - // Java objects are wrapped as TemplateHashModelEx-s. + + // Java objects are wrapped as TemplateHashModelEx-s. return getObjectDump(model, unwrappedModel); } @@ -320,13 +323,18 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel { TemplateModelIterator iModel = keys.iterator(); while (iModel.hasNext()) { String key = iModel.next().toString(); + // Workaround this oddity: model.object does not contain + // values for "empty" and "keys", but model.keys() does. + if ("class".equals(key) || "empty".equals(key)) { + continue; + } TemplateModel value = model.get(key); - items.put(key, getDump(value)); - } + items.put(key, getDump(value)); + } map.put(Key.VALUE.toString(), items); return map; } - + private Map getObjectDump(TemplateHashModelEx model, Object object) throws TemplateModelException { Map map = new HashMap(); @@ -388,11 +396,9 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel { continue; } } - // Else look for the entire methodName in the key set. Include those - // starting with "get" or "is" that were not found above. - // NB This does not properly account for methods exposed as properties - // using BeansWrapper.finetuneMethodAppearance(), and perhaps other - // changes to method exposure through that method. + + // Else look for the entire methodName in the key set, to include + // those that are exposed as methods rather than properties. if (keySet.contains(methodName)) { String methodDisplayName = getMethodDisplayName(method); // If no arguments, invoke the method to get the result