diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/dump/DescribeDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/dump/DescribeDirective.java index 9faf90a82..42ca3b606 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/dump/DescribeDirective.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/dump/DescribeDirective.java @@ -71,7 +71,7 @@ public class DescribeDirective extends BaseTemplateDirectiveModel { } DumpHelper helper = new DumpHelper(env); - List methods = helper.getMethodsAvailableToTemplate(unwrappedModel.getClass()); + List methods = helper.getMethodsAvailableToTemplate(tm, unwrappedModel.getClass()); List methodDisplayNames = new ArrayList(methods.size()); for (Method m : methods) { methodDisplayNames.add(helper.getMethodDisplayName(m)); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/dump/DumpHelper.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/dump/DumpHelper.java index 5f028ceaf..2a96a439b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/dump/DumpHelper.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/dump/DumpHelper.java @@ -18,11 +18,12 @@ import edu.cornell.mannlib.vitro.webapp.utils.StringUtils; import edu.cornell.mannlib.vitro.webapp.web.directives.BaseTemplateDirectiveModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; import freemarker.core.Environment; +import freemarker.ext.beans.BeanModel; +import freemarker.ext.beans.BeansWrapper; +import freemarker.ext.beans.WrapperExtractor; import freemarker.template.TemplateBooleanModel; import freemarker.template.TemplateDateModel; -import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateHashModel; -import freemarker.template.TemplateMethodModel; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; import freemarker.template.TemplateNumberModel; @@ -44,7 +45,7 @@ public class DumpHelper { return BaseTemplateDirectiveModel.processTemplateToString("dump-var.ftl", map, env); } - public Map getVariableDumpData(String varName) { + private Map getVariableDumpData(String varName) { TemplateHashModel dataModel = env.getDataModel(); TemplateModel tm = null; @@ -63,7 +64,7 @@ public class DumpHelper { Map map = new HashMap(); map.put("var", varName); - if (tm != null) { + if (tm != null) { Object unwrappedModel = null; try { unwrappedModel = DeepUnwrap.permissiveUnwrap(tm); @@ -86,7 +87,7 @@ public class DumpHelper { // view in the dump. Not sure if we should handle our application-specific, non-template // model objects in the same way. For now, these get assigned a shorthand type below. if (unwrappedModel instanceof BaseTemplateModel) { - value = getTemplateModelDump((BaseTemplateModel)unwrappedModel); //((BaseTemplateModel)unwrappedModel).dump(); + value = getTemplateModelDump(tm, (BaseTemplateModel)unwrappedModel); //((BaseTemplateModel)unwrappedModel).dump(); type = className; } // Can't use this, because tm of (at least some) POJOs are @@ -109,10 +110,6 @@ public class DumpHelper { type = "Sequence"; } else if (tm instanceof TemplateHashModel) { type = "Hash"; - // In recursive dump, we've gotten down to a raw string. Just output it. - // } else if (val == null) { - // out.write(var); - // return; } else { // One of the above cases should have applied. Just in case not, show the Java class name. type = className; @@ -120,7 +117,6 @@ public class DumpHelper { map.put("value", value); map.put("type", type); - } return map; @@ -136,28 +132,40 @@ public class DumpHelper { } } - protected List getMethodsAvailableToTemplate(Class cls) { + protected List getMethodsAvailableToTemplate(TemplateModel wrappedModel, Class cls) { List methods = new ArrayList(); // Go up the class hierarchy only as far as the immediate subclass of BaseTemplateModel if (! cls.getName().equals("edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel")) { - methods = getDeclaredPublicMethods(cls); - methods.addAll(getMethodsAvailableToTemplate(cls.getSuperclass())); + methods = getDeclaredMethodsAvailableToTemplate(wrappedModel, cls); + methods.addAll(getMethodsAvailableToTemplate(wrappedModel, cls.getSuperclass())); } return methods; } - private List getDeclaredPublicMethods(Class cls) { + private List getDeclaredMethodsAvailableToTemplate(TemplateModel wrappedModel, Class cls) { List methods = new ArrayList(); Method[] declaredMethods = cls.getDeclaredMethods(); - for (Method m : declaredMethods) { - int mod = m.getModifiers(); + for (Method method : declaredMethods) { + int mod = method.getModifiers(); if (Modifier.isPublic(mod) && !Modifier.isStatic(mod)) { - // If the method takes args, make sure the BeanWrapper used makes this method visible. - // RY It may not be possible to determine this. - methods.add(m); + Class[] params = method.getParameterTypes(); + // If the method takes arguments... + if (params.length > 0) { + // Unless the object has been wrapped with a non-default BeansWrapper with an exposure + // level that is more permissive than the Configuration's default BeansWrapper, this + // method is not visible to the template. + if ( ! ( wrappedModel instanceof BeanModel ) ) { + continue; + } + int exposureLevel = WrapperExtractor.getWrapperExposureLevel((BeanModel)wrappedModel); + if ( exposureLevel > BeansWrapper.EXPOSE_SAFE ) { + continue; + } + } + methods.add(method); } } return methods; @@ -186,11 +194,15 @@ public class DumpHelper { return methodName + paramList; } - private String getTemplateModelDump(BaseTemplateModel model) { + private String getTemplateModelDump(TemplateModel wrappedModel, BaseTemplateModel unwrappedModel) { + +// if (tm instanceof BeanModel) { +// int exposureLevel = WrapperExtractor.getWrapperExposureLevel((BeanModel) tm); +// log.debug(varName + " is an instance of BeanModel. Exposure level = " + exposureLevel); +// } - log.debug(model.getClass()); Map map = new HashMap(); - List publicMethods = getMethodsAvailableToTemplate(model.getClass()); + List publicMethods = getMethodsAvailableToTemplate(wrappedModel, unwrappedModel.getClass()); Map properties = new HashMap(); List methods = new ArrayList(); for (Method method : publicMethods) { @@ -200,18 +212,8 @@ public class DumpHelper { methods.add(key); } else { try { - Object result = method.invoke(model); - String value = null; - if (result == null) { - value = "null"; // distinguish a null from an empty string -// } else if (result instanceof TemplateDirectiveModel) { -// // value = string output of the help() method processed through template -// } else if (result instanceof TemplateMethodModel) { -// // value = string output of the help() method processed through template - } else { - value = result.toString(); - } - + Object result = method.invoke(unwrappedModel); + String value = result == null ? "null" : result.toString(); properties.put(key, value); } catch (Exception e) { log.error(e, e); diff --git a/webapp/src/freemarker/ext/beans/WrapperExtractor.java b/webapp/src/freemarker/ext/beans/WrapperExtractor.java new file mode 100644 index 000000000..808521c7a --- /dev/null +++ b/webapp/src/freemarker/ext/beans/WrapperExtractor.java @@ -0,0 +1,20 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package freemarker.ext.beans; + +import freemarker.template.TemplateModel; + +/** + * Class to extract information about the wrapper used to wrap an object in + * the template model. + */ +public class WrapperExtractor { + + public static BeansWrapper getWrapper(BeanModel model) { + return model.wrapper; + } + + public static int getWrapperExposureLevel(BeanModel model) { + return model.wrapper.getExposureLevel(); + } +} diff --git a/webapp/web/templates/freemarker/body/partials/dump/dump-tm.ftl b/webapp/web/templates/freemarker/body/partials/dump/dump-tm.ftl index 1a4c8b3de..841052add 100644 --- a/webapp/web/templates/freemarker/body/partials/dump/dump-tm.ftl +++ b/webapp/web/templates/freemarker/body/partials/dump/dump-tm.ftl @@ -1,8 +1,10 @@ <#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> -<#-- Template for dumping a template model object --> +<#-- Template for dumping the value template model object --> + <#if properties?has_content> +

Property values

    <#list properties?keys as property>
  • ${property}: ${properties[property]?html}
  • @@ -11,9 +13,13 @@ <#if methods?has_content> +

    Methods

      <#list methods as method>
    • ${method}
    - \ No newline at end of file + + + + diff --git a/webapp/web/templates/freemarker/body/test.ftl b/webapp/web/templates/freemarker/body/test.ftl index 1dc72abb8..520140eef 100644 --- a/webapp/web/templates/freemarker/body/test.ftl +++ b/webapp/web/templates/freemarker/body/test.ftl @@ -3,3 +3,7 @@ <#-- FreeMarker test cases -->

    ${title}

    + +<@dumpAll /> + +