Example #1
0
 public MacroMenuRenderer(
     String macroLibraryPath, HttpServletRequest request, HttpServletResponse response)
     throws TemplateException, IOException {
   this.macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath);
   this.request = request;
   this.response = response;
 }
 private Environment getEnvironment(Appendable writer) throws TemplateException, IOException {
   Environment environment = environments.get(writer);
   if (environment == null) {
     Map<String, Object> input = UtilMisc.toMap("key", null);
     environment = FreeMarkerWorker.renderTemplate(macroLibrary, input, writer);
     environments.put(writer, environment);
   }
   return environment;
 }
Example #3
0
 private void executeMacro(Appendable writer, String macro) throws IOException, TemplateException {
   Environment environment = getEnvironment(writer);
   Reader templateReader = new StringReader(macro);
   macroCount++;
   String templateName = toString().concat("_") + macroCount;
   Template template =
       new Template(templateName, templateReader, FreeMarkerWorker.getDefaultOfbizConfig());
   templateReader.close();
   environment.include(template);
 }
 private void executeMacro(Appendable writer, String macro) throws IOException {
   try {
     Environment environment = getEnvironment(writer);
     Reader templateReader = new StringReader(macro);
     // FIXME: I am using a Date as an hack to provide a unique name for the template...
     Template template =
         new Template(
             (new java.util.Date()).toString(),
             templateReader,
             FreeMarkerWorker.getDefaultOfbizConfig());
     templateReader.close();
     environment.include(template);
   } catch (TemplateException e) {
     Debug.logError(e, "Error rendering screen macro [" + macro + "] thru ftl", module);
   } catch (IOException e) {
     Debug.logError(e, "Error rendering screen macro [" + macro + "] thru ftl", module);
   }
 }
  @SuppressWarnings("unchecked")
  public Writer getWriter(final Writer out, Map args) {
    final StringBuilder buf = new StringBuilder();
    final Environment env = Environment.getCurrentEnvironment();
    final Map<String, Object> templateCtx = FreeMarkerWorker.getWrappedObject("context", env);
    // FreeMarkerWorker.convertContext(templateCtx);
    final Map<String, Object> savedValues = FreeMarkerWorker.saveValues(templateCtx, saveKeyNames);
    FreeMarkerWorker.overrideWithArgs(templateCtx, args);
    final Delegator delegator = FreeMarkerWorker.getWrappedObject("delegator", env);
    /*
            final String editTemplate = FreeMarkerWorker.getArg(args, "editTemplate", ctx);
            final String wrapTemplateId = FreeMarkerWorker.getArg(args, "wrapTemplateId", ctx);
            //final String mapKey = FreeMarkerWorker.getArg(args, "mapKey", ctx);
            final String templateContentId = FreeMarkerWorker.getArg(args, "templateContentId", ctx);
            final String subDataResourceTypeId = FreeMarkerWorker.getArg(args, "subDataResourceTypeId", ctx);
            final String contentId = FreeMarkerWorker.getArg(args, "contentId", ctx);
            final String subContentId = FreeMarkerWorker.getArg(args, "subContentId", ctx);
            final String rootDir = FreeMarkerWorker.getArg(args, "rootDir", ctx);
            final String webSiteId = FreeMarkerWorker.getArg(args, "webSiteId", ctx);
            final String https = FreeMarkerWorker.getArg(args, "https", ctx);
            final String viewSize = FreeMarkerWorker.getArg(args, "viewSize", ctx);
            final String viewIndex = FreeMarkerWorker.getArg(args, "viewIndex", ctx);
            final String listSize = FreeMarkerWorker.getArg(args, "listSize", ctx);
            final String highIndex = FreeMarkerWorker.getArg(args, "highIndex", ctx);
            final String lowIndex = FreeMarkerWorker.getArg(args, "lowIndex", ctx);
            final String queryString = FreeMarkerWorker.getArg(args, "queryString", ctx);
            final Locale locale = FreeMarkerWorker.getWrappedObject("locale", env);
            final String mimeTypeId = FreeMarkerWorker.getArg(args, "mimeTypeId", ctx);
    */
    final LocalDispatcher dispatcher = FreeMarkerWorker.getWrappedObject("dispatcher", env);
    // final GenericValue userLogin = FreeMarkerWorker.getWrappedObject("userLogin", env);
    GenericValue view = FreeMarkerWorker.getWrappedObject("subContentDataResourceView", env);
    final Integer indent =
        (templateCtx.get("indent") == null)
            ? Integer.valueOf(0)
            : (Integer) templateCtx.get("indent");

    String contentId = (String) templateCtx.get("contentId");
    String subContentId = (String) templateCtx.get("subContentId");
    if (view == null) {
      String thisContentId = subContentId;
      if (UtilValidate.isEmpty(thisContentId)) {
        thisContentId = contentId;
      }
      if (UtilValidate.isNotEmpty(thisContentId)) {
        try {
          view = delegator.findByPrimaryKey("Content", UtilMisc.toMap("contentId", thisContentId));
        } catch (GenericEntityException e) {
          Debug.logError(e, "Error getting sub-content", module);
          throw new RuntimeException(e.getMessage());
        }
      }
    }

    final GenericValue subContentDataResourceView = view;
    final Map<String, Object> traverseContext = FastMap.newInstance();
    traverseContext.put("delegator", delegator);
    Map<String, Object> whenMap = FastMap.newInstance();
    whenMap.put("followWhen", templateCtx.get("followWhen"));
    whenMap.put("pickWhen", templateCtx.get("pickWhen"));
    whenMap.put("returnBeforePickWhen", templateCtx.get("returnBeforePickWhen"));
    whenMap.put("returnAfterPickWhen", templateCtx.get("returnAfterPickWhen"));
    traverseContext.put("whenMap", whenMap);
    String fromDateStr = (String) templateCtx.get("fromDateStr");
    String thruDateStr = (String) templateCtx.get("thruDateStr");
    Timestamp fromDate = null;
    if (UtilValidate.isNotEmpty(fromDateStr)) {
      fromDate = UtilDateTime.toTimestamp(fromDateStr);
    }
    traverseContext.put("fromDate", fromDate);
    Timestamp thruDate = null;
    if (UtilValidate.isNotEmpty(thruDateStr)) {
      thruDate = UtilDateTime.toTimestamp(thruDateStr);
    }
    traverseContext.put("thruDate", thruDate);
    String startContentAssocTypeId = (String) templateCtx.get("contentAssocTypeId");
    if (startContentAssocTypeId != null) startContentAssocTypeId = "SUB_CONTENT";
    traverseContext.put("contentAssocTypeId", startContentAssocTypeId);
    String direction = (String) templateCtx.get("direction");
    if (UtilValidate.isEmpty(direction)) direction = "From";
    traverseContext.put("direction", direction);

    return new LoopWriter(out) {

      @Override
      public void write(char cbuf[], int off, int len) {
        // StringBuilder ctxBuf = (StringBuilder) templateContext.get("buf");
        // ctxBuf.append(cbuf, off, len);
        buf.append(cbuf, off, len);
      }

      @Override
      public void flush() throws IOException {
        out.flush();
      }

      @Override
      public int onStart() throws TemplateModelException, IOException {
        // templateContext.put("buf", new StringBuilder());
        List<Map<String, Object>> nodeTrail = FastList.newInstance();
        traverseContext.put("nodeTrail", nodeTrail);
        // GenericValue content = null;
        /*
                        if (UtilValidate.isNotEmpty(contentId)) {
                            try {
                                content = delegator.findByPrimaryKey("Content", UtilMisc.toMap("contentId", contentId));
                            } catch (GenericEntityException e) {
                                // TODO: Not sure what to put here.
                                throw new RuntimeException(e.getMessage());
                            }
                        }
        */
        Map<String, Object> rootNode = ContentWorker.makeNode(subContentDataResourceView);
        ContentWorker.traceNodeTrail("1", nodeTrail);
        ContentWorker.selectKids(rootNode, traverseContext);
        ContentWorker.traceNodeTrail("2", nodeTrail);
        nodeTrail.add(rootNode);
        boolean isPick =
            checkWhen(
                subContentDataResourceView, (String) traverseContext.get("contentAssocTypeId"));
        rootNode.put("isPick", Boolean.valueOf(isPick));
        if (!isPick) {
          ContentWorker.traceNodeTrail("3", nodeTrail);
          isPick = ContentWorker.traverseSubContent(traverseContext);
          ContentWorker.traceNodeTrail("4", nodeTrail);
        }
        if (isPick) {
          populateContext(traverseContext, templateCtx);
          ContentWorker.traceNodeTrail("5", nodeTrail);
          return TransformControl.EVALUATE_BODY;
        } else {
          return TransformControl.SKIP_BODY;
        }
      }

      @Override
      public int afterBody() throws TemplateModelException, IOException {
        // out.write(buf.toString());
        // buf.setLength(0);
        // templateContext.put("buf", new StringBuilder());
        List<Map<String, Object>> nodeTrail =
            UtilGenerics.checkList(traverseContext.get("nodeTrail"));
        ContentWorker.traceNodeTrail("6", nodeTrail);
        boolean inProgress = ContentWorker.traverseSubContent(traverseContext);
        ContentWorker.traceNodeTrail("7", nodeTrail);
        if (inProgress) {
          populateContext(traverseContext, templateCtx);
          ContentWorker.traceNodeTrail("8", nodeTrail);
          return TransformControl.REPEAT_EVALUATION;
        } else return TransformControl.END_EVALUATION;
      }

      @Override
      public void close() throws IOException {
        String wrappedFTL = buf.toString();
        String encloseWrappedText = (String) templateCtx.get("encloseWrappedText");
        if (UtilValidate.isEmpty(encloseWrappedText)
            || encloseWrappedText.equalsIgnoreCase("false")) {
          out.write(wrappedFTL);
          wrappedFTL = null; // So it won't get written again below.
        }
        String wrapTemplateId = (String) templateCtx.get("wrapTemplateId");
        if (UtilValidate.isNotEmpty(wrapTemplateId)) {
          templateCtx.put("wrappedFTL", wrappedFTL);
          Map<String, Object> templateRoot = FreeMarkerWorker.createEnvironmentMap(env);
          /*
                              templateRoot.put("viewSize", viewSize);
                              templateRoot.put("viewIndex", viewIndex);
                              templateRoot.put("listSize", listSize);
                              templateRoot.put("highIndex", highIndex);
                              templateRoot.put("lowIndex", lowIndex);
                              templateRoot.put("queryString", queryString);
                              templateRoot.put("wrapDataResourceTypeId", subDataResourceTypeId);
                              templateRoot.put("wrapContentIdTo", contentId);
                              templateRoot.put("wrapMimeTypeId", mimeTypeId);
                              //templateRoot.put("wrapMapKey", mapKey);

          */
          templateRoot.put("context", templateCtx);
          String mimeTypeId = (String) templateCtx.get("mimeTypeId");
          Locale locale = (Locale) templateCtx.get("locale");
          if (locale == null) locale = Locale.getDefault();
          try {
            ContentWorker.renderContentAsText(
                dispatcher,
                delegator,
                wrapTemplateId,
                out,
                templateRoot,
                locale,
                mimeTypeId,
                null,
                null,
                true);
          } catch (GeneralException e) {
            Debug.logError(e, "Error rendering content", module);
            throw new IOException("Error rendering content" + e.toString());
          }
          /*
                              Map resultsCtx = FreeMarkerWorker.getWrappedObject("context", env);
                              templateContext.put("contentId", contentId);
                              templateContext.put("locale", locale);
                              templateContext.put("mapKey", null);
                              templateContext.put("subContentId", null);
                              templateContext.put("templateContentId", null);
                              templateContext.put("subDataResourceTypeId", null);
                              templateContext.put("mimeTypeId", null);
          */
        } else {
          if (UtilValidate.isNotEmpty(wrappedFTL)) out.write(wrappedFTL);
        }
        FreeMarkerWorker.removeValues(templateCtx, removeKeyNames);
        FreeMarkerWorker.reloadValues(templateCtx, savedValues, env);
      }

      private boolean checkWhen(GenericValue thisContent, String contentAssocTypeId) {
        boolean isPick = false;
        Map<String, Object> assocContext = FastMap.newInstance();
        if (UtilValidate.isEmpty(contentAssocTypeId)) {
          contentAssocTypeId = "";
        }
        assocContext.put("contentAssocTypeId", contentAssocTypeId);
        // assocContext.put("contentTypeId", assocValue.get("contentTypeId"));
        // String assocRelation = null;
        String thisDirection = (String) templateCtx.get("direction");
        String thisContentId = (String) templateCtx.get("thisContentId");
        // String relatedDirection = null;
        if (thisDirection != null && thisDirection.equalsIgnoreCase("From")) {
          assocContext.put("contentIdFrom", thisContentId);
          // assocRelation = "FromContent";
          // relatedDirection = "From";
        } else {
          assocContext.put("contentIdTo", thisContentId);
          // assocRelation = "ToContent";
          // relatedDirection = "To";
        }
        assocContext.put("content", thisContent);
        List<Object> purposes = ContentWorker.getPurposes(thisContent);
        assocContext.put("purposes", purposes);
        List<String> contentTypeAncestry = FastList.newInstance();
        String contentTypeId = (String) thisContent.get("contentTypeId");
        try {
          ContentWorker.getContentTypeAncestry(delegator, contentTypeId, contentTypeAncestry);
        } catch (GenericEntityException e) {
          return false;
        }
        assocContext.put("typeAncestry", contentTypeAncestry);
        Map<String, Object> whenMap = UtilGenerics.checkMap(traverseContext.get("whenMap"));
        // String pickWhen = (String)whenMap.get("pickWhen");
        List<Map<String, ? extends Object>> nodeTrail =
            UtilGenerics.checkList(traverseContext.get("nodeTrail"));
        int indentSz = indent.intValue() + nodeTrail.size();
        assocContext.put("indentObj", Integer.valueOf(indentSz));
        isPick = ContentWorker.checkWhen(assocContext, (String) whenMap.get("pickWhen"));
        return isPick;
      }

      public void populateContext(
          Map<String, Object> traverseContext, Map<String, Object> templateContext) {
        List<Map<String, Object>> nodeTrail =
            UtilGenerics.checkList(traverseContext.get("nodeTrail"));
        int sz = nodeTrail.size();
        Map<String, Object> node = nodeTrail.get(sz - 1);
        // GenericValue content = (GenericValue)node.get("value");
        String contentId = (String) node.get("contentId");
        // String subContentId = (String)node.get("subContentId");
        templateContext.put("subContentId", contentId);
        templateContext.put("subContentDataResourceView", null);
        int indentSz = indent.intValue() + nodeTrail.size();
        templateContext.put("indent", Integer.valueOf(indentSz));
        if (sz >= 2) {
          Map<String, Object> parentNode = nodeTrail.get(sz - 2);
          GenericValue parentContent = (GenericValue) parentNode.get("value");
          String parentContentId = (String) parentNode.get("contentId");
          templateContext.put("parentContentId", parentContentId);
          templateContext.put("parentContent", parentContent);
          templateContext.put("nodeTrail", nodeTrail);
        }
      }
    };
  }
 /** @deprecated use FreeMarkerWorker.getArg() */
 @Deprecated
 public static String getArg(Map<String, Object> args, String key, Map<String, Object> ctx) {
   return FreeMarkerWorker.getArg(args, key, ctx);
 }
 /** @deprecated use FreeMarkerWorker.getArg() */
 @Deprecated
 public static String getArg(Map<String, Object> args, String key, Environment env) {
   return FreeMarkerWorker.getArg(args, key, env);
 }
 /**
  * @deprecated use FreeMarkerWorker.getWrappedObject() A wrapper for the FreeMarkerWorker version.
  */
 @Deprecated
 public static Object getWrappedObject(String varName, Environment env) {
   return FreeMarkerWorker.getWrappedObject(varName, env);
 }
/** Widget Library - Screen model HTML class. */
@SuppressWarnings("serial")
public class HtmlWidget extends ModelScreenWidget {
  public static final String module = HtmlWidget.class.getName();

  public static UtilCache<String, Template> specialTemplateCache =
      UtilCache.createUtilCache("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 {
    @Override
    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);
    }

    @Override
    public String getAsString() {
      return StringUtil.htmlEncoder.encode(super.getAsString());
    }
  }

  // End Static, begin class section

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

  public HtmlWidget(ModelScreen modelScreen, Element htmlElement) {
    super(modelScreen, htmlElement);
    List<? extends Element> childElementList = UtilXml.childElementList(htmlElement);
    for (Element childElement : childElementList) {
      if ("html-template".equals(childElement.getNodeName())) {
        this.subWidgets.add(new HtmlTemplate(modelScreen, childElement));
      } else if ("html-template-decorator".equals(childElement.getNodeName())) {
        this.subWidgets.add(new HtmlTemplateDecorator(modelScreen, childElement));
      } else {
        throw new IllegalArgumentException(
            "Tag not supported under the platform-specific -> html tag with name: "
                + childElement.getNodeName());
      }
    }
  }

  @Override
  public void renderWidgetString(
      Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer)
      throws GeneralException, IOException {
    for (ModelScreenWidget subWidget : subWidgets) {
      subWidget.renderWidgetString(writer, context, screenStringRenderer);
    }
  }

  @Override
  public String rawString() {
    StringBuilder buffer = new StringBuilder("<html-widget>");
    for (ModelScreenWidget subWidget : subWidgets) {
      buffer.append(subWidget.rawString());
    }
    buffer.append("</html-widget>");
    return buffer.toString();
  }

  public static void renderHtmlTemplate(
      Appendable writer, FlexibleStringExpander locationExdr, Map<String, Object> context) {
    String location = locationExdr.expandString(context);
    // Debug.logInfo("Rendering template at location [" + location + "] with context: \n" + context,
    // module);

    if (UtilValidate.isEmpty(location)) {
      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"));
        boolean insertWidgetBoundaryComments =
            ModelWidget.widgetBoundaryCommentsEnabled(parameters);
        if (insertWidgetBoundaryComments) {
          writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin", "Template", location));
        }

        // FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
        Template template = null;
        if (location.endsWith(".fo.ftl")) { // FOP can't render correctly escaped characters
          template = FreeMarkerWorker.getTemplate(location);
        } else {
          template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig);
        }
        FreeMarkerWorker.renderTemplate(template, context, writer);

        if (insertWidgetBoundaryComments) {
          writer.append(HtmlWidgetRenderer.formatBoundaryComment("End", "Template", location));
        }
      } catch (IllegalArgumentException e) {
        String errMsg =
            "Error rendering included template at location [" + location + "]: " + e.toString();
        Debug.logError(e, errMsg, module);
        writeError(writer, errMsg);
      } catch (MalformedURLException e) {
        String errMsg =
            "Error rendering included template at location [" + location + "]: " + e.toString();
        Debug.logError(e, errMsg, module);
        writeError(writer, errMsg);
      } catch (TemplateException e) {
        String errMsg =
            "Error rendering included template at location [" + location + "]: " + e.toString();
        Debug.logError(e, errMsg, module);
        writeError(writer, errMsg);
      } catch (IOException e) {
        String errMsg =
            "Error rendering included template at location [" + location + "]: " + e.toString();
        Debug.logError(e, errMsg, module);
        writeError(writer, errMsg);
      }
    } else {
      throw new IllegalArgumentException(
          "Rendering not yet supported for the template at location: " + location);
    }
  }

  // TODO: We can make this more fancy, but for now this is very functional
  public static void writeError(Appendable writer, String message) {
    try {
      writer.append(message);
    } catch (IOException e) {
    }
  }

  public static class HtmlTemplate extends ModelScreenWidget {
    protected FlexibleStringExpander locationExdr;

    public HtmlTemplate(ModelScreen modelScreen, Element htmlTemplateElement) {
      super(modelScreen, htmlTemplateElement);
      this.locationExdr =
          FlexibleStringExpander.getInstance(htmlTemplateElement.getAttribute("location"));
    }

    @Override
    public void renderWidgetString(
        Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
      renderHtmlTemplate(writer, this.locationExdr, context);
    }

    @Override
    public String rawString() {
      return "<html-template location=\"" + this.locationExdr.getOriginal() + "\"/>";
    }
  }

  public static class HtmlTemplateDecorator extends ModelScreenWidget {
    protected FlexibleStringExpander locationExdr;
    protected Map<String, HtmlTemplateDecoratorSection> sectionMap = FastMap.newInstance();

    public HtmlTemplateDecorator(ModelScreen modelScreen, Element htmlTemplateDecoratorElement) {
      super(modelScreen, htmlTemplateDecoratorElement);
      this.locationExdr =
          FlexibleStringExpander.getInstance(htmlTemplateDecoratorElement.getAttribute("location"));

      List<? extends Element> htmlTemplateDecoratorSectionElementList =
          UtilXml.childElementList(htmlTemplateDecoratorElement, "html-template-decorator-section");
      for (Element htmlTemplateDecoratorSectionElement : htmlTemplateDecoratorSectionElementList) {
        String name = htmlTemplateDecoratorSectionElement.getAttribute("name");
        this.sectionMap.put(
            name,
            new HtmlTemplateDecoratorSection(modelScreen, htmlTemplateDecoratorSectionElement));
      }
    }

    @Override
    public void renderWidgetString(
        Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
      // isolate the scope
      MapStack<String> contextMs;
      if (!(context instanceof MapStack)) {
        contextMs = MapStack.create(context);
        context = contextMs;
      } else {
        contextMs = UtilGenerics.cast(context);
      }

      // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a
      // new "screens" object just for it so it is isolated and doesn't follow the stack down
      MapStack<String> standAloneStack = contextMs.standAloneChildStack();
      standAloneStack.put(
          "screens", new ScreenRenderer(writer, standAloneStack, screenStringRenderer));
      SectionsRenderer sections =
          new SectionsRenderer(this.sectionMap, standAloneStack, writer, screenStringRenderer);

      // put the sectionMap in the context, make sure it is in the sub-scope, ie after calling push
      // on the MapStack
      contextMs.push();
      context.put("sections", sections);

      renderHtmlTemplate(writer, this.locationExdr, context);
      contextMs.pop();
    }

    @Override
    public String rawString() {
      return "<html-template-decorator location=\"" + this.locationExdr.getOriginal() + "\"/>";
    }
  }

  public static class HtmlTemplateDecoratorSection extends ModelScreenWidget {
    protected String name;
    protected List<ModelScreenWidget> subWidgets;

    public HtmlTemplateDecoratorSection(
        ModelScreen modelScreen, Element htmlTemplateDecoratorSectionElement) {
      super(modelScreen, htmlTemplateDecoratorSectionElement);
      this.name = htmlTemplateDecoratorSectionElement.getAttribute("name");
      // read sub-widgets
      List<? extends Element> subElementList =
          UtilXml.childElementList(htmlTemplateDecoratorSectionElement);
      this.subWidgets = ModelScreenWidget.readSubWidgets(this.modelScreen, subElementList);
    }

    @Override
    public void renderWidgetString(
        Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer)
        throws GeneralException, IOException {
      // render sub-widgets
      renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);
    }

    @Override
    public String rawString() {
      return "<html-template-decorator-section name=\"" + this.name + "\"/>";
    }
  }
}
Example #10
0
  public static void renderHtmlTemplate(
      Appendable writer, FlexibleStringExpander locationExdr, Map<String, Object> context) {
    String location = locationExdr.expandString(context);
    // Debug.logInfo("Rendering template at location [" + location + "] with context: \n" + context,
    // module);

    if (UtilValidate.isEmpty(location)) {
      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"));
        boolean insertWidgetBoundaryComments =
            ModelWidget.widgetBoundaryCommentsEnabled(parameters);
        if (insertWidgetBoundaryComments) {
          writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin", "Template", location));
        }

        // FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
        Template template = null;
        if (location.endsWith(".fo.ftl")) { // FOP can't render correctly escaped characters
          template = FreeMarkerWorker.getTemplate(location);
        } else {
          template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig);
        }
        FreeMarkerWorker.renderTemplate(template, context, writer);

        if (insertWidgetBoundaryComments) {
          writer.append(HtmlWidgetRenderer.formatBoundaryComment("End", "Template", location));
        }
      } catch (IllegalArgumentException e) {
        String errMsg =
            "Error rendering included template at location [" + location + "]: " + e.toString();
        Debug.logError(e, errMsg, module);
        writeError(writer, errMsg);
      } catch (MalformedURLException e) {
        String errMsg =
            "Error rendering included template at location [" + location + "]: " + e.toString();
        Debug.logError(e, errMsg, module);
        writeError(writer, errMsg);
      } catch (TemplateException e) {
        String errMsg =
            "Error rendering included template at location [" + location + "]: " + e.toString();
        Debug.logError(e, errMsg, module);
        writeError(writer, errMsg);
      } catch (IOException e) {
        String errMsg =
            "Error rendering included template at location [" + location + "]: " + e.toString();
        Debug.logError(e, errMsg, module);
        writeError(writer, errMsg);
      }
    } else {
      throw new IllegalArgumentException(
          "Rendering not yet supported for the template at location: " + location);
    }
  }
 public MacroScreenRenderer(String name, String macroLibraryPath)
     throws TemplateException, IOException {
   macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath);
   rendererName = name;
 }
Example #12
0
  @SuppressWarnings("unchecked")
  public Writer getWriter(final Writer out, Map args) {
    final Environment env = Environment.getCurrentEnvironment();
    // final Map templateCtx = FreeMarkerWorker.getWrappedObject("context", env);
    // final Map templateCtx = new HashMap<String, Object>();
    final LocalDispatcher dispatcher = FreeMarkerWorker.getWrappedObject("dispatcher", env);
    final Delegator delegator = FreeMarkerWorker.getWrappedObject("delegator", env);
    final HttpServletRequest request = FreeMarkerWorker.getWrappedObject("request", env);
    final HttpServletResponse response = FreeMarkerWorker.getWrappedObject("response", env);
    final Map<String, Object> templateRoot = FreeMarkerWorker.createEnvironmentMap(env);
    if (Debug.verboseOn()) {
      Debug.logVerbose(
          "in RenderSubContent, contentId(0):" + templateRoot.get("contentId"), module);
    }
    FreeMarkerWorker.getSiteParameters(request, templateRoot);
    final Map<String, Object> savedValuesUp = new HashMap<String, Object>();
    FreeMarkerWorker.saveContextValues(templateRoot, upSaveKeyNames, savedValuesUp);
    FreeMarkerWorker.overrideWithArgs(templateRoot, args);
    if (Debug.verboseOn()) {
      Debug.logVerbose(
          "in RenderSubContent, contentId(2):" + templateRoot.get("contentId"), module);
    }
    // not used yet: final GenericValue userLogin = FreeMarkerWorker.getWrappedObject("userLogin",
    // env);
    // not used yet: List trail = (List)templateRoot.get("globalNodeTrail");
    // if (Debug.infoOn()) Debug.logInfo("in Render(0), globalNodeTrail ." + trail , module);
    // not used yet: String contentAssocPredicateId =
    // (String)templateRoot.get("contentAssocPredicateId");
    // not used yet: String strNullThruDatesOnly = (String)templateRoot.get("nullThruDatesOnly");
    // not used yet: Boolean nullThruDatesOnly = (strNullThruDatesOnly != null &&
    // strNullThruDatesOnly.equalsIgnoreCase("true")) ? Boolean.TRUE :Boolean.FALSE;
    final String thisContentId = (String) templateRoot.get("contentId");
    final String xmlEscape = (String) templateRoot.get("xmlEscape");
    final boolean directAssocMode = UtilValidate.isNotEmpty(thisContentId) ? true : false;
    if (Debug.verboseOn()) {
      Debug.logVerbose("in Render(0), directAssocMode ." + directAssocMode, module);
    }
    /*
    if (Debug.infoOn()) Debug.logInfo("in Render(0), thisSubContentId ." + thisSubContentId , module);
    String thisSubContentId =  (String)templateRoot.get("subContentId");
    GenericValue val = null;
    try {
        val = FreeMarkerWorker.getCurrentContent(delegator, trail, userLogin, templateRoot, nullThruDatesOnly, contentAssocPredicateId);
    } catch (GeneralException e) {
        throw new RuntimeException("Error getting current content. " + e.toString());
    }
    final GenericValue view = val;

    String dataResourceId = null;
    String subContentIdSub = null;
    if (view != null) {
        try {
            dataResourceId = (String) view.get("drDataResourceId");
        } catch (Exception e) {
            dataResourceId = (String) view.get("dataResourceId");
        }
        subContentIdSub = (String) view.get("contentId");
    }
    // This order is taken so that the dataResourceType can be overridden in the transform arguments.
    String subDataResourceTypeId = (String)templateRoot.get("subDataResourceTypeId");
    if (UtilValidate.isEmpty(subDataResourceTypeId)) {
        try {
            subDataResourceTypeId = (String) view.get("drDataResourceTypeId");
        } catch (Exception e) {
            // view may be "Content"
        }
        // TODO: If this value is still empty then it is probably necessary to get a value from
        // the parent context. But it will already have one and it is the same context that is
        // being passed.
    }
    String mimeTypeId = FreeMarkerWorker.getMimeTypeId(delegator, view, templateRoot);
    templateRoot.put("drDataResourceId", dataResourceId);
    templateRoot.put("mimeTypeId", mimeTypeId);
    templateRoot.put("dataResourceId", dataResourceId);
    templateRoot.put("subContentId", subContentIdSub);
    templateRoot.put("subDataResourceTypeId", subDataResourceTypeId);
    */

    final Map<String, Object> savedValues = new HashMap<String, Object>();

    return new Writer(out) {

      @Override
      public void write(char cbuf[], int off, int len) {}

      @Override
      public void flush() throws IOException {
        out.flush();
      }

      @Override
      public void close() throws IOException {
        List<Map<String, ? extends Object>> globalNodeTrail =
            UtilGenerics.checkList(templateRoot.get("globalNodeTrail"));
        if (Debug.verboseOn()) {
          Debug.logVerbose(
              "Render close, globalNodeTrail(2a):" + ContentWorker.nodeTrailToCsv(globalNodeTrail),
              "");
        }
        renderSubContent();
        // if (Debug.verboseOn()) Debug.logVerbose("in Render(2), globalNodeTrail ." +
        // getWrapped(env, "globalNodeTrail") , module);
      }

      public void renderSubContent() throws IOException {
        String mimeTypeId = (String) templateRoot.get("mimeTypeId");
        Object localeObject = templateRoot.get("locale");
        Locale locale = null;
        if (localeObject == null) {
          locale = UtilHttp.getLocale(request);
        } else {
          locale = UtilMisc.ensureLocale(localeObject);
        }

        // TemplateHashModel dataRoot = env.getDataModel();
        // Timestamp fromDate = UtilDateTime.nowTimestamp();
        // List passedGlobalNodeTrail = (List)templateRoot.get("globalNodeTrail");
        String editRequestName = (String) templateRoot.get("editRequestName");
        if (Debug.verboseOn()) {
          Debug.logVerbose("in Render(3), editRequestName ." + editRequestName, module);
        }
        /*
        GenericValue thisView = null;
        if (view != null) {
            thisView = view;
        } else if (passedGlobalNodeTrail.size() > 0) {
            Map map = (Map)passedGlobalNodeTrail.get(passedGlobalNodeTrail.size() - 1);
            if (Debug.infoOn()) Debug.logInfo("in Render(3), map ." + map , module);
            if (map != null)
                thisView = (GenericValue)map.get("value");
        }
        if (Debug.verboseOn()) Debug.logVerbose("in RenderSubContent, subContentId:" + templateRoot.get("subContentId"), module);
        if (Debug.verboseOn()) Debug.logVerbose("in RenderSubContent, contentId:" + templateRoot.get("contentId"), module);
        */

        if (UtilValidate.isNotEmpty(editRequestName)) {
          String editStyle = getEditStyle();
          openEditWrap(out, editStyle);
        }

        if (Debug.verboseOn()) {
          Debug.logVerbose(
              "in RenderSubContent, contentId(2):" + templateRoot.get("contentId"), module);
          Debug.logVerbose(
              "in RenderSubContent, subContentId(2):" + templateRoot.get("subContentId"), module);
        }
        FreeMarkerWorker.saveContextValues(templateRoot, saveKeyNames, savedValues);
        // if (thisView != null) {
        try {
          String txt =
              ContentWorker.renderContentAsText(
                  dispatcher, delegator, thisContentId, templateRoot, locale, mimeTypeId, true);
          if ("true".equals(xmlEscape)) {
            txt = UtilFormatOut.encodeXmlValue(txt);
          }

          out.write(txt);

          // if (Debug.infoOn()) Debug.logInfo("in RenderSubContent, after
          // renderContentAsTextCache:", module);
        } catch (GeneralException e) {
          String errMsg = "Error rendering thisContentId:" + thisContentId + " msg:" + e.toString();
          Debug.logError(e, errMsg, module);
          // just log a message and don't return anything: throw new IOException();
        }
        // }
        FreeMarkerWorker.reloadValues(templateRoot, savedValuesUp, env);
        FreeMarkerWorker.reloadValues(templateRoot, savedValues, env);
        if (UtilValidate.isNotEmpty(editRequestName)) {
          closeEditWrap(out, editRequestName);
        }

        // if (Debug.infoOn()) Debug.logInfo("in Render(4), globalNodeTrail ." + getWrapped(env,
        // "globalNodeTrail") , module);
      }

      public void openEditWrap(Writer out, String editStyle) throws IOException {
        String divStr = "<div class=\"" + editStyle + "\">";
        out.write(divStr);
      }

      public void closeEditWrap(Writer out, String editRequestName) throws IOException {
        if (Debug.infoOn()) {
          Debug.logInfo(
              "in RenderSubContent, contentId(3):" + templateRoot.get("contentId"), module);
          Debug.logInfo(
              "in RenderSubContent, subContentId(3):" + templateRoot.get("subContentId"), module);
        }
        String fullRequest = editRequestName;
        String contentId = null;
        contentId = (String) templateRoot.get("subContentId");
        String delim = "?";
        if (UtilValidate.isNotEmpty(contentId)) {
          fullRequest += delim + "contentId=" + contentId;
          delim = "&";
        }

        out.write("<a href=\"");
        ServletContext servletContext = request.getSession().getServletContext();
        RequestHandler rh = (RequestHandler) servletContext.getAttribute("_REQUEST_HANDLER_");
        out.append(rh.makeLink(request, response, "/" + fullRequest, false, false, true));
        out.write("\">Edit</a>");
        out.write("</div>");
      }

      public String getEditStyle() {
        String editStyle = (String) templateRoot.get("editStyle");
        if (UtilValidate.isEmpty(editStyle)) {
          editStyle = UtilProperties.getPropertyValue("content", "defaultEditStyle");
        }
        if (UtilValidate.isEmpty(editStyle)) {
          editStyle = "buttontext";
        }
        return editStyle;
      }
    };
  }
  @SuppressWarnings("unchecked")
  public Writer getWriter(final Writer out, Map args) {
    final StringBuilder buf = new StringBuilder();
    final Environment env = Environment.getCurrentEnvironment();
    final Map<String, Object> templateCtx = FreeMarkerWorker.createEnvironmentMap(env);
    // FreeMarkerWorker.convertContext(templateCtx);
    final Delegator delegator = FreeMarkerWorker.getWrappedObject("delegator", env);
    final HttpServletRequest request = FreeMarkerWorker.getWrappedObject("request", env);
    final GenericValue userLogin = FreeMarkerWorker.getWrappedObject("userLogin", env);
    FreeMarkerWorker.getSiteParameters(request, templateCtx);
    FreeMarkerWorker.overrideWithArgs(templateCtx, args);
    final String mode = (String) templateCtx.get("mode");
    final String quickCheckContentId = (String) templateCtx.get("quickCheckContentId");
    final Map<String, Object> savedValues = FastMap.newInstance();
    // Debug.logInfo("in CheckPermission, contentId(1):" + templateCtx.get("contentId"),"");
    // Debug.logInfo("in CheckPermission, subContentId(1):" + templateCtx.get("subContentId"),"");

    return new LoopWriter(out) {

      @Override
      public void write(char cbuf[], int off, int len) {
        buf.append(cbuf, off, len);
      }

      @Override
      public void flush() throws IOException {
        out.flush();
      }

      @Override
      public int onStart() throws TemplateModelException, IOException {
        List<Map<String, ? extends Object>> trail =
            UtilGenerics.checkList(templateCtx.get("globalNodeTrail"));
        // String trailCsv = ContentWorker.nodeTrailToCsv(trail);
        // Debug.logInfo("in CheckPermission, trailCsv(2):" + trailCsv,"");
        // Debug.logInfo("in CheckPermission, contentId(2):" + templateCtx.get("contentId"),"");
        // Debug.logInfo("in CheckPermission, subContentId(2):" +
        // templateCtx.get("subContentId"),"");

        GenericValue currentContent = null;
        String contentAssocPredicateId = (String) templateCtx.get("contentAssocPredicateId");
        String strNullThruDatesOnly = (String) templateCtx.get("nullThruDatesOnly");
        Boolean nullThruDatesOnly =
            (strNullThruDatesOnly != null && strNullThruDatesOnly.equalsIgnoreCase("true"))
                ? Boolean.TRUE
                : Boolean.FALSE;
        GenericValue val = null;
        try {
          val =
              ContentWorker.getCurrentContent(
                  delegator,
                  trail,
                  userLogin,
                  templateCtx,
                  nullThruDatesOnly,
                  contentAssocPredicateId);
        } catch (GeneralException e) {
          throw new RuntimeException("Error getting current content. " + e.toString());
        }
        // final GenericValue view = val;
        currentContent = val;
        if (currentContent != null) {
          // Debug.logInfo("in CheckPermission, currentContent(0):" +
          // currentContent.get("contentId"),"");
        }

        if (currentContent == null) {
          currentContent = delegator.makeValue("Content");
          currentContent.put("ownerContentId", templateCtx.get("ownerContentId"));
        }
        // Debug.logInfo("in CheckPermission, currentContent(1):" +
        // currentContent.get("contentId"),"");

        Security security = null;
        if (request != null) {
          security = (Security) request.getAttribute("security");
        }

        String statusId = (String) currentContent.get("statusId");
        String passedStatusId = (String) templateCtx.get("statusId");
        List<String> statusList = StringUtil.split(passedStatusId, "|");
        if (statusList == null) {
          statusList = FastList.newInstance();
        }
        if (UtilValidate.isNotEmpty(statusId) && !statusList.contains(statusId)) {
          statusList.add(statusId);
        }
        String targetPurpose = (String) templateCtx.get("contentPurposeList");
        List<String> purposeList = StringUtil.split(targetPurpose, "|");
        String entityOperation = (String) templateCtx.get("entityOperation");
        String targetOperation = (String) templateCtx.get("targetOperation");
        if (UtilValidate.isEmpty(targetOperation)) {
          if (UtilValidate.isNotEmpty(entityOperation)) {
            targetOperation = "CONTENT" + entityOperation;
          }
        }
        List<String> targetOperationList = StringUtil.split(targetOperation, "|");
        if (targetOperationList.size() == 0) {
          // Debug.logInfo("in CheckPermission, entityOperation:" + entityOperation,"");
          // Debug.logInfo("in CheckPermission, templateCtx:" + templateCtx,"");
          throw new IOException("targetOperationList has zero size.");
        }
        List<String> roleList = FastList.newInstance();

        String privilegeEnumId = (String) currentContent.get("privilegeEnumId");
        Map<String, Object> results =
            EntityPermissionChecker.checkPermission(
                currentContent,
                statusList,
                userLogin,
                purposeList,
                targetOperationList,
                roleList,
                delegator,
                security,
                entityOperation,
                privilegeEnumId,
                quickCheckContentId);

        boolean isError =
            ModelService.RESPOND_ERROR.equals(results.get(ModelService.RESPONSE_MESSAGE));
        if (isError) {
          throw new IOException(ModelService.RESPONSE_MESSAGE);
        }

        String permissionStatus = (String) results.get("permissionStatus");

        if (UtilValidate.isEmpty(permissionStatus) || !permissionStatus.equals("granted")) {
          String errorMessage = "Permission to add response is denied (2)";
          PermissionRecorder recorder = (PermissionRecorder) results.get("permissionRecorder");
          // Debug.logInfo("recorder(0):" + recorder, "");
          if (recorder != null) {
            String permissionMessage = recorder.toHtml();
            // Debug.logInfo("permissionMessage(0):" + permissionMessage, "");
            errorMessage += " \n " + permissionMessage;
          }
          templateCtx.put("permissionErrorMsg", errorMessage);
        }

        if (permissionStatus != null && permissionStatus.equalsIgnoreCase("granted")) {
          FreeMarkerWorker.saveContextValues(templateCtx, saveKeyNames, savedValues);
          if (mode == null || !mode.equalsIgnoreCase("not-equals"))
            return TransformControl.EVALUATE_BODY;
          else return TransformControl.SKIP_BODY;
        } else {
          if (mode == null || !mode.equalsIgnoreCase("not-equals"))
            return TransformControl.SKIP_BODY;
          else return TransformControl.EVALUATE_BODY;
        }
      }

      @Override
      public void close() throws IOException {
        FreeMarkerWorker.reloadValues(templateCtx, savedValues, env);
        String wrappedContent = buf.toString();
        out.write(wrappedContent);
      }
    };
  }